Volatile关键字
Volatile关键字
参考:
http://blog.****.net/jsonChumpKlutz/article/details/78364332
http://blog.****.net/chenloxiaoea/article/details/47041227
http://blog.****.net/seu_calvin/article/details/52370068
线程的内存模型:
1、 线程从主内存取得的对象,仅仅是对象副本,线程内修改不影响主内存。
2、 当我们修改完共享变量的时候,需要把改过的变量写入主存中,这样才能让其他线程获取到正确的值。
3、 每个线程私有工作区间别的线程是无法访问的。
Jvm的原子性、可见性、有序性
原子性:
对基本类型变量的读取和赋值操作是原子性操作,即这些操作是不可中断的,要么执行完毕,要么就不执行。
Eg:
x =3; //语句1
y =4 //语句2
z = x+y ;//语句3
x++; //语句4
这里面的操作只有语句1和语句2是原子性的操作,语句3,4不是原子性的操作;因为再语句3中包括了三个操作,1是先读取x的值,2读取y的值,3将z的值写入内存中。语句4的解释是一样的。一般的一个语句含有多个操作该语句就不是原子性的操作,只有简单的读取和赋值才是原子性的操作。
可见性
就是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。也就是一个线程修改结果,另一个线程马上就能看到。
有序性
Java内存模型允许编译器和处理器对指令进行重排序,虽然重排序不会影响到单线程的正确性,但是会影响到多线程的正确性。
Volatile关键字
作用:
1.不保证原子性。
2.保证有序性。
3.保证可见性。
当用volatile修饰共享变量的时候,线程访问到该变量的时候都回去主存中去取该变量的值,它的工作内存中的缓存将失效,这样就保证了每个线程访问该变量的时候都是从主存中读写的。这就是为什么使用Volatile关键字来修饰线程间共享变量。
使用:
注意点:
volatile具有synchronized关键字的“可见性”,但是没有synchronized关键字的“并发正确性”,也就是说不保证线程执行的有序性。(也就是说,volatile变量对于每次使用,线程都能得到当前volatile变量的最新值。但是volatile变量并不保证并发的正确性),jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的。所以说volatile是线程不安全的。
synchronized
这里提到volatile就提一下synchronized。
Synchronized可作用于对象、方法。即可保证可见性,又能够保证原子性。
可见性体现在:通过synchronized或者Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存中。
原子性表现在:要么不执行,要么执行到底。
相对于volatile因为其要保证原子性,就影响执行效率。在不需要强调执行循序的时候我们就用volatile就好了。