关于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 搞死了...谢谢
Global site tag (gtag.js) - Google Analytics