Snowberg

 

Java中的synchronized和volatile

刚开始看Netty,第一个文件Bootstrap,就发现使用了很多volatile关键字。 
赶紧补充一下Java线程同步机制的知识。有错误的地方,请大家指正。 

说到Java的线程同步问题肯定要说到两个关键字synchronized和volatile。说到这两个关键字,又要说道JVM的内存模型。JVM里内存分为main memory和working memory。 

Main memory是所有线程共享的,working memory则是线程的工作内存,它保存有部分main memory变量的拷贝,对这些变量的更新直接发生在working memory里,并在适当的时候写回main memory(很遗憾,我对这个“适当的时候”并不是十分清楚,^_^)。这样如果有多个线程访问同一个变量,就会发生同步问题。 

synchronized是常用的同步手段,它可以用来同步程序块,甚至整个函数。但有时候synchronized显得太过粗放。提高多线程程序性能的一个要点就是尽量把同步的粒度最小化,最好做到share nothing, no synchronization。 

volatile就是一种粒度更小的同步手段。当然volatile关键字的原始语义并不是用来做同步的。volatile的字面意思是“易变的”,用这个关键字修饰变量就是要告诉JVM,这个变量会被多个线程访问,不要把它放到working memory里,而只有main memory一个拷贝,所有对它的操作都在main memory里进行。由于在32位机器上,对基本类型int, char等的存取操作都在一个指令内完成,也就是说是原子的,这就给线程之间同步共享数据提供了一种力度更小,效率更高的手段。但对long,double等基本类型,由于对它们的操作需要多条指令(原因是其是有64位组成,在读写这些变量时,一次要读写32位,因此需要两次读取,在这期间有可能产生字撕裂现象),不是原子的,所以就不是线程安全的。但是加上volatile关键字之后,这些变量也操作也具有了原子特性。 volatile关键字保证了原子性和可见性两个特性。

这和C/C++中的volatile语义是差不多的,C/C++中的寄存器就是这里的working memory,内存就是main memory。可以说在Java1.4之前,Java和C/C++里volatile的语义基本一致。 

但Java1.5里,volatile的语义被扩充完善,自动扩展了对double,float等基本类型为原子操作。(这点我不是很确定,也许有人要拍我了)

来自:http://wugc.iteye.com/blog/986944

posted on 2011-11-28 20:04  Snowberg  阅读(355)  评论(0编辑  收藏  举报

导航