Java volatile 关键字

  • 2016-01-09
  • 3,061
  • 0

Java 内存模型:

线程安全:

  • 原子性:由Java内存模型直接保证的原子性变量操作包括read,load,user,assign,stroe,write,大致可认为Java基础数据类型的读写是具备原子性的。Java内存模型还提供了lock和unlock,由高层字节码指令monitorenter和monitorexit隐匿地使用,反应到Java代码就是synchronized关键字。因此synchronized块直接的操作也是原子性的。
  • 可见性:当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。volatile的特殊规则保证了新值能够立即同步到主内存,以及每次使用前立即从主内存刷新,保证了线程操作变量的可见性。
    synchronized和final关键字也能保证可见性。final关键字的可见性是指:被final修饰的变量一旦构造器初始化完成,并且没有把this引用传递出去,那么其他线程就能看到最新的值。
  • 有序性:如果在本线程内观察,所有操作都是有序的;如果在一个线程中观察另一个线程,所有操作都是无序的。前半句是指“线程内表现为串行语义”,后半句是指“指令重排序”现象和“工作内存主主内存同步延迟”现象。

Java语言提供了volatile和synchronized两个关键字来保证线程之间操作的有序性,volatile关键字本身就包含了禁止指令重排序的语义,而synchronized则是由“一个变量在同一时刻只允许一条线程对其进行lock操作”这条规则来获得的,这个规则决定了持有同一个锁的两个同步块只能串行地进入。

重排序:

在执行程序时为了提高性能,编译器和处理器经常会对指令进行重排序。 重排序分成三种类型:

  • 编译器优化的重排序。编译器在不改变单线程程序语义放入前提下,可以重新安排语句的执行顺序。
  • 指令级并行的重排序。现代处理器采用了指令级并行技术来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
  • 内存系统的重排序。由于处理器使用缓存和读写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。

为了保证内存的可见性,Java编译器在生成指令序列的适当位置会插入内存屏障指令来禁止特定类型的处理器重排序。Java内存模型把内存屏障分为LoadLoad、LoadStore、StoreLoad和StoreStore四种。

>> 转载请注明来源:Java volatile 关键字

评论

还没有任何评论,你来说两句吧

发表评论