Java中的volatile关键字
分类:Android, Java
阅读 (1,214)
Add comments
8月 062017
volatile保证共享变量在多程中的可见性
即一个共享变量在线程1中被修改在,在线程2中读取这个变量时,立即得到最新的值
volatile不能保证变量的原子性
比较经典的一个例子就是用一个boolean变量判断线程是否停止的例子,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
public class ThreadTest { static volatile boolean isrunning = false; static class Thread1 extends Thread{ @Override public void run() { super.run(); isrunning = true; int counter = 0; while (true){ counter++; System.out.println("counter: " + counter); if(counter > 10000){ break; } } isrunning = false; System.out.println("thread1 finish"); } } static class Thread2 extends Thread{ @Override public void run() { super.run(); while (true){ if(!isrunning){ break; } } System.out.println("thread2 finish"); } } public static void main(String[] args){ Thread1 thread1 = new Thread1(); Thread2 thread2 = new Thread2(); thread1.start(); thread2.start(); } } |
如果isrunning不加volatile修饰,thread2一直无法停止,因为无法获取到isrunning的更新状态。
volatile修饰对象
被volatile修饰的对象,当对象内所有成员的值变化时都会更新到主存中, 以确保成员的可见性?(未亲自测试过)
一些其他的见解:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。 Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。 这样当多个线程同时与某个对象交互时,就必须要注意到要让线程及时的得到共享成员变量的变化。 而volatile关键字就是提示VM:对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。 使用建议:在两个或者更多的线程访问的成员变量上使用volatile。当要访问的变量已在synchronized代码块中,或者为常量时,不必使用。 由于使用volatile屏蔽掉了VM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。 就跟C中的一样 禁止编译器进行优化~~~~ |
摘自:https://bbs.csdn.net/topics/390413948?page=1