线程笔记-volatile
2016-09-23 17:33
99 查看
缓存一致性协议:最出名的就是Intel 的MESI协议,MESI协议保证了每个缓存中使用的共享变量的副本是一致的。它核心的思想是:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取。
volatile:当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。
一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
2)禁止进行指令重排序。
在有限的一些情形下使用 volatile 变量替代锁。要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:
1)对变量的写操作不依赖于当前值。
2)该变量没有包含在具有其他变量的不变式中。
volatile的原理和实现机制
前面讲述了源于volatile关键字的一些使用,下面我们来探讨一下volatile到底如何保证可见性和禁止指令重排序的。
下面这段话摘自《深入理解Java虚拟机》:
“观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令”
lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:
1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
2)它会强制将对缓存的修改操作立即写入主存;
3)如果是写操作,它会导致其他CPU中对应的缓存行无效。
**注意:**volatile通常某个操作的完成、发生中断或状态的标示,不能确保操作的原值行(例如:i++)。
单例设计模式:
参考:http://www.cnblogs.com/dolphin0520/p/3920373.html
http://www.ibm.com/developerworks/cn/java/j-jtp06197.html
经典:http://blog.csdn.net/wxwzy738/article/details/43238089
volatile与static的区别
参考:http://blog.sina.com.cn/s/blog_4e1e357d0101i486.html
volatile:当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。
一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
2)禁止进行指令重排序。
在有限的一些情形下使用 volatile 变量替代锁。要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:
1)对变量的写操作不依赖于当前值。
2)该变量没有包含在具有其他变量的不变式中。
package thread.basic._volatile.demo2; public class Volatile2 extends Object implements Runnable { //value变量没有被标记为volatile private int value; //missedIt变量被标记为volatile private volatile boolean missedIt; public Volatile2() { value = 0; missedIt = false; } public void run() { System.out.println(Thread.currentThread().toString()+"..entering run()"); //循环检查value的值是否不同 while ( missedIt ) { System.out.println(Thread.currentThread().toString()+"..printing..."+value++); } System.out.println(Thread.currentThread().toString()+"..leaving run()"); } public void setStop(){ missedIt = false; } public void setStart(){ missedIt = true; } public static void main(String[] args) { try { //通过该构造函数可以获取实时时钟的当前时间 Volatile2 vol = new Volatile2(); Thread t = new Thread(vol); Thread t2 = new Thread(vol); Thread t3 = new Thread(vol); vol.setStart(); //设置关闭 t.start(); // Thread.sleep(10); // vol.setStop(); t2.start(); Thread.sleep(10); vol.setStop(); t3.start(); } catch ( InterruptedException x ) { System.err.println("one of the sleeps was interrupted"); } } }
volatile的原理和实现机制
前面讲述了源于volatile关键字的一些使用,下面我们来探讨一下volatile到底如何保证可见性和禁止指令重排序的。
下面这段话摘自《深入理解Java虚拟机》:
“观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令”
lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:
1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
2)它会强制将对缓存的修改操作立即写入主存;
3)如果是写操作,它会导致其他CPU中对应的缓存行无效。
**注意:**volatile通常某个操作的完成、发生中断或状态的标示,不能确保操作的原值行(例如:i++)。
单例设计模式:
class Singleton{ private volatile static Singleton instance = null; private Singleton() { } public static Singleton getInstance() { if(instance==null) { synchronized (Singleton.class) { if(instance==null) instance = new Singleton(); } } return instance; } }
参考:http://www.cnblogs.com/dolphin0520/p/3920373.html
http://www.ibm.com/developerworks/cn/java/j-jtp06197.html
经典:http://blog.csdn.net/wxwzy738/article/details/43238089
volatile与static的区别
参考:http://blog.sina.com.cn/s/blog_4e1e357d0101i486.html
相关文章推荐
- Java多核线程笔记-volatile的原理与技巧
- Java多核线程笔记-volatile的原理与技巧
- Java多核线程笔记-volatile的原理与技巧
- Java多核线程笔记-volatile的原理与技巧
- Java多核线程笔记-volatile的原理与技巧
- Java多核线程笔记-volatile的原理与技巧
- Java多核线程笔记-volatile的原理与技巧
- Java多核线程笔记-volatile的原理与技巧
- 线程笔记
- Java线程笔记一:
- 孙鑫VC学习笔记:第十六讲 (一) 利用事件对象实现线程间的同步
- APUE Chapter 11笔记:UNIX下的线程(II)
- 学习笔记:windows下,用c语言来创建线程
- 孙鑫VC学习笔记:第十五讲 (一) 进程和线程基本概念
- Java线程笔记三:
- linux学习笔记-线程(1)
- 孙鑫VC学习笔记:第十六讲 (二) 利用关键代码段实现线程间的同步
- 孙鑫VC学习笔记:第十五讲 进程和线程基本概念
- 孙鑫VC学习笔记:第十六讲 利用关键代码段实现线程间的同步
- 四种线程间的通信(笔记)