关于volatile关键字的疑惑
pingyuyue
2012-02-21
xiaoyu 写道 pingyuyue 写道 xiaoyu 写道 开关都是建议使用 while 而不是 if (这本书也有讲的吧, 没讲的话, 找一本java多线程编程来看吧).
volatile 保证了可见性, 但是不保证其他的. 这个“可见性”其实也是有点不安全的; 比如线程A和B,A修改了volatile变量i;B只有进行取值原子操作的时候才能感应到更新;但是B若在A修改i之前已经进行了取值原子操作,这样就不会感应到i已经变了,所以短暂的数据不一致; 个人理解,请指教 你理解有误... 你这样的假设永远都拿不到新值....保证可见性, 是值当volatile的变量被写后, 后面所有的读,都能看到这个写的值. 还是有点模糊 “值当volatile的变量被写后, 后面所有的读,都能看到这个写的值”. 这个“后面所有的读”就是指取值操作对吧,当然也是后面的读,若是在修改之前读了,不就不一致了吗? volatile boolean shut; public void shutdown() { shut = true; } public void doWork() { while (!shut) { // do something } }这段代码,假如A先获取了shut,切换B也读取了shut,切换A修改shut ,B仍然从工作内存拿到shut的值,而这个值是过期的 ,这就是不可见的啊 |
|
pingyuyue
2012-02-21
xiaoyu 写道 pingyuyue 写道 xiaoyu 写道 开关都是建议使用 while 而不是 if (这本书也有讲的吧, 没讲的话, 找一本java多线程编程来看吧).
volatile 保证了可见性, 但是不保证其他的. 这个“可见性”其实也是有点不安全的; 比如线程A和B,A修改了volatile变量i;B只有进行取值原子操作的时候才能感应到更新;但是B若在A修改i之前已经进行了取值原子操作,这样就不会感应到i已经变了,所以短暂的数据不一致; 个人理解,请指教 你理解有误... 你这样的假设永远都拿不到新值....保证可见性, 是值当volatile的变量被写后, 后面所有的读,都能看到这个写的值. 按照上述说法,可以仔细试想下用volatile做计数器 ,也是可以的,可事实不可以 |
|
xiaoyu
2012-02-21
pingyuyue 写道 xiaoyu 写道 pingyuyue 写道 xiaoyu 写道 开关都是建议使用 while 而不是 if (这本书也有讲的吧, 没讲的话, 找一本java多线程编程来看吧).
volatile 保证了可见性, 但是不保证其他的. 这个“可见性”其实也是有点不安全的; 比如线程A和B,A修改了volatile变量i;B只有进行取值原子操作的时候才能感应到更新;但是B若在A修改i之前已经进行了取值原子操作,这样就不会感应到i已经变了,所以短暂的数据不一致; 个人理解,请指教 你理解有误... 你这样的假设永远都拿不到新值....保证可见性, 是值当volatile的变量被写后, 后面所有的读,都能看到这个写的值. 按照上述说法,可以仔细试想下用volatile做计数器 ,也是可以的,可事实不可以 它保证可见性, 不保证原子性. 怎么做计数器? |
|
pingyuyue
2012-02-21
xiaoyu 写道 pingyuyue 写道 xiaoyu 写道 pingyuyue 写道 xiaoyu 写道 开关都是建议使用 while 而不是 if (这本书也有讲的吧, 没讲的话, 找一本java多线程编程来看吧).
volatile 保证了可见性, 但是不保证其他的. 这个“可见性”其实也是有点不安全的; 比如线程A和B,A修改了volatile变量i;B只有进行取值原子操作的时候才能感应到更新;但是B若在A修改i之前已经进行了取值原子操作,这样就不会感应到i已经变了,所以短暂的数据不一致; 个人理解,请指教 你理解有误... 你这样的假设永远都拿不到新值....保证可见性, 是值当volatile的变量被写后, 后面所有的读,都能看到这个写的值. 按照上述说法,可以仔细试想下用volatile做计数器 ,也是可以的,可事实不可以 它保证可见性, 不保证原子性. 怎么做计数器? 有点明白了,如果不保证原子性,就可能读到过期的数据 |
|
xiaoyu
2012-02-22
pingyuyue 写道 xiaoyu 写道 pingyuyue 写道 xiaoyu 写道 pingyuyue 写道 xiaoyu 写道 开关都是建议使用 while 而不是 if (这本书也有讲的吧, 没讲的话, 找一本java多线程编程来看吧).
volatile 保证了可见性, 但是不保证其他的. 这个“可见性”其实也是有点不安全的; 比如线程A和B,A修改了volatile变量i;B只有进行取值原子操作的时候才能感应到更新;但是B若在A修改i之前已经进行了取值原子操作,这样就不会感应到i已经变了,所以短暂的数据不一致; 个人理解,请指教 你理解有误... 你这样的假设永远都拿不到新值....保证可见性, 是值当volatile的变量被写后, 后面所有的读,都能看到这个写的值. 按照上述说法,可以仔细试想下用volatile做计数器 ,也是可以的,可事实不可以 它保证可见性, 不保证原子性. 怎么做计数器? 有点明白了,如果不保证原子性,就可能读到过期的数据 你需要看这个 http://java.sun.com/docs/books/jls/second_edition/html/memory.doc.html Threads and Locks 当然, 你那本深入理解 java 虚拟机, 也有部分段落的。 |
|
heavensay
2012-02-22
xiaoyu 写道 有点明白了,如果不保证原子性,就可能读到过期的数据
volatile修饰的变量,不能保证其++,--等操作的原之性。 2个线程同一时刻可能读到一个相同的值,然后各自++,然后2个线程又把相加后相同的值,写回到内存中,造成了一种一次++,被[遗漏]了。也就引起100次的++操作,可能最后得到的值会小于100(i的初值为0)。 |
|
pingyuyue
2012-02-22
xiaoyu 写道 pingyuyue 写道 xiaoyu 写道 pingyuyue 写道 xiaoyu 写道 pingyuyue 写道 xiaoyu 写道 开关都是建议使用 while 而不是 if (这本书也有讲的吧, 没讲的话, 找一本java多线程编程来看吧).
volatile 保证了可见性, 但是不保证其他的. 这个“可见性”其实也是有点不安全的; 比如线程A和B,A修改了volatile变量i;B只有进行取值原子操作的时候才能感应到更新;但是B若在A修改i之前已经进行了取值原子操作,这样就不会感应到i已经变了,所以短暂的数据不一致; 个人理解,请指教 你理解有误... 你这样的假设永远都拿不到新值....保证可见性, 是值当volatile的变量被写后, 后面所有的读,都能看到这个写的值. 按照上述说法,可以仔细试想下用volatile做计数器 ,也是可以的,可事实不可以 它保证可见性, 不保证原子性. 怎么做计数器? 有点明白了,如果不保证原子性,就可能读到过期的数据 你需要看这个 http://java.sun.com/docs/books/jls/second_edition/html/memory.doc.html Threads and Locks 当然, 你那本深入理解 java 虚拟机, 也有部分段落的。 已经明白了 ,谢谢 |
|
RednaxelaFX
2012-02-22
xiaoyu 写道 你需要看这个 http://java.sun.com/docs/books/jls/second_edition/html/memory.doc.html
Threads and Locks 当然, 你那本深入理解 java 虚拟机, 也有部分段落的。 不要看JLS第二版里的那段。要看新的。 http://rednaxelafx.iteye.com/blog/1081626 |
|
xiaoyu
2012-02-23
RednaxelaFX 写道 xiaoyu 写道 你需要看这个 http://java.sun.com/docs/books/jls/second_edition/html/memory.doc.html
Threads and Locks 当然, 你那本深入理解 java 虚拟机, 也有部分段落的。 不要看JLS第二版里的那段。要看新的。 http://rednaxelafx.iteye.com/blog/1081626 但是真被load store 搞死了...谢谢 |