Java内存模型

来源:互联网 发布:彩虹无人机 知乎 编辑:程序博客网 时间:2024/06/05 16:02

单线程执行程序会按照给定的程序顺序执行,保证了程序的顺序一致性,即程序运行结果和预期是一致的。但是,在多线程的环境下,会出现编译器和处理器对程序的重排列,这将打乱程序的顺序一致性,得不到预期结果,引起这种结果的原因是数据之间的相关性,在多线程环境下,没有正确的数据传递关系,导致错误运行结果。所以在Java语言中,为了得到运行正确性的保障,JSR-133有了happens-before的规范,保证:1、对于会改变程序结果的重排序禁止重排序;2、不会改变结果的重排序允许。为了达到这一目标,Java语言提供一些关键字和方法,让程序员去保证一定的内存可见性,如锁、volatile等方法,这些关键字确保了内存可见性,因为它们在底层提供了一些支持,利用屏障去禁止一些能产生错误的编译器重排序和处理器重排序,确保程序的运行正确。

Volatile变量所能提供的特性有:1、可见性,对一个volatile变量的读,总能使这个线程看到其他线程的写(缓存一致性);2、原子性,对单个volatile变量的读写具有原子性。所以它的内存语义是:当写一个volatile变量时,JMM会把该线程的本地内存中的共享变量刷新到主内存;当读一个volatile变量时,JMM会把该线程对应的本地内存缓存置为无效,从主内存重新读入;它实现了线程之间的数据通信,这个内存语义的实现底层采用了一些屏障,保证了如:volatile写操作之前有个屏障,不管什么操作,完成以后才能使用volatile写操作;volatile读操作之后有个屏障,只有读操作完成以后,才能进行后续操作;当第一个volatile写,第二个volatile读,这两个不能重排列;

volatile只能保障对单个volatile变量的读写原子性,所以当多个操作时,保障原子性操作的只能使用锁;锁可以让临界区互斥执行。锁的内存语义:1、线程释放锁时,JMM会把本地内存的共享变量刷新到主内存中;2、线程获取锁,会把本地内存置为无效,从而监视器保护的临界区从主内存中读取共享变量。

从数据通信角度来看,锁释放和获取和volatile保证了同等的happens-before原则。只是锁的实现原理不同,它是借助于同步器框架AQS来维持这个效果。(后面具体叙述)

0 0
原创粉丝点击