volatile会保护我免受所有幕后多线程危害吗?

时间:2014-03-12 08:55:21

标签: java android multithreading volatile

我曾经认为只有两种多线程危险:

  1. 竞争条件:一个线程读取x,然后它可以写回另一个线程写x
  2. 状态不稳定:一个线程写入xy,但在这两个写入之间,另一个线程会读取x的新值{\ n} {1}}旧值,即使这些变量应该一起更改。
  3. 我认为如果我可以说这些事情不会发生,我就不需要同步了。但是从an argument over the D language forums我了解到,编译器,CPU和内存在幕后工作的方式可能存在其他危险:

    1. 编译器和CPU都可以以不影响单线程执行的方式更改指令的顺序,但可能会破坏我对非同步线程安全性的推理。例如,可以分配一个对象并将其分配给线程共享变量,然后才会调用构造函数。它在单线程中并不重要,但是使用多线程,另一个线程现在可以访问未初始化的对象。
    2. 缓存意味着即使操作顺序正确,全局内存和本地缓存之间的同步也会影响一个线程可以看到另一个线程的更改。
    3. 未对齐的指针大小的写入不是原子的,在某些体系结构中,即使是对齐的写入也可能不是原子的,因此当另一个线程读取它时,指针本身可能已损坏(=处于不稳定状态),因为写入它的线程只写了一半的字节。
    4. 我现在正在研究一个Android项目,我再次面临类似的问题 - 我可以推断某些功能在竞争条件和不稳定状态下是安全的,但不是关于这三种幕后危险。

      我遇到了Java y成员字段,从我收集的内容中它使用内存屏障来防止CPU搞乱执行顺序(显然编译器不会搞砸了如果它阻止CPU这样做,那么它应该解决第一个危险。但是其他两个呢?

      • 它是否解决了缓存问题?操作系统负责的缓存是不是?它是否通知操作系统,强制它刷新缓存?
      • 它是否解决了非原子写入问题?它是否强制变量对齐并使用JVM的运行时知识来使用同步,即使对齐的指针大小的写入不是原子的?

      换句话说 - 如果我可以推断竞争条件和不稳定状态不是问题,并将共享变量标记为volatile,那么不使用同步是否安全?

1 个答案:

答案 0 :(得分:1)

我不知道第一个和第三个问题(关于第一个问题的一些链接如果你确定它会很好)但是我确定它修复了你的第二个问题,因为volatile确保刷新本地缓存。

有关此主题,请参阅thisthis

<强>更新

我想我找到了你问题的完美链接:

http://javarevisited.blogspot.com/2011/06/volatile-keyword-java-example-tutorial.html#ixzz2vjymNleY

<强> 1。关于重新排序

  

顺便使用volatile关键字也会阻止编译器或JVM重新排序代码或将它们从同步障碍中移开。

<强> 2。关于缓存

  

Java中的Volatile用作Java编译器和Thread的指示符,它不缓存此变量的值并始终从主内存中读取

第3。关于原子读写

  

在Java中,读取和写入对于使用Java volatile关键字声明的所有变量都是原子的(包括长变量和双变量)。