Atomic actions cannot be interleaved,so they can be used without fear of thread interference. However,this does not eliminate all need to synchronize atomic actions,because memory consistency errors are still possible. Using volatile variables reduces the risk of memory consistency errors,because any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable. This means that changes to a volatile variable are always visible to other threads. What’s more,it also means that when a thread reads a volatile variable,it sees not just the latest change to the volatile,but also the side effects of the code that led up the change.
它还说:
>读取和写入对于参考变量和大多数都是原子的
原始变量(除long和double之外的所有类型).
>读取和写入对于声明为volatile的所有变量都是原子的(包括long
和双变量).
关于这些陈述,我有两个问题:
>“使用volatile变量可降低内存一致性错误的风险” – 它们的意思是“降低风险”,以及使用volatile时内存一致性错误如何仍然存在?
>将volatile放在非双非长基元上的唯一效果是,是否可以启用与其他线程后续读取的“先发生”关系?我问这个,因为看起来那些变量已经有了原子读数.
解决方法
原子性是Java内存模型解决的一个问题.但是,比Atomicity更重要的是以下问题:
>内存架构,例如cpu缓存对读写操作的影响
> cpu优化,例如重新装载货物和商店
>编译器优化,例如添加和删除装载和存储
以下清单包含一个经常使用的示例.对x和y的操作是原子的.不过,该程序可以打印两行.
int x = 0,y = 0; // thread 1 x = 1 if (y == 0) System.out.println("foo"); // thread 2 y = 1 if (x == 0) System.out.println("bar");
但是,如果将x和y声明为volatile,则只能打印两行中的一行.
使用volatile时,内存一致性错误如何仍然存在?
以下示例使用volatile.但是,更新可能仍会丢失.
int x = 0; // thread 1 x += 1; // thread 2 x += 1;
如果说将volatile放在非双非长基元上的唯一效果是启用与其他线程后续读取的“先发生”关系吗?
以前发生的事情经常被误解.由before-before定义的一致性模型很弱并且难以正确使用.这可以通过以下示例进行演示,该示例称为独立写入独立读取(IRIW):
volatile int x = 0,y = 0; // thread 1 x = 1; // thread 2 y = 1; // thread 3 if (x == 1) System.out.println(y); // thread 4 if (y == 1) System.out.println(x);
只有在发生之前,两个0才是有效的结果.然而,这显然是违反直觉的.因此,Java提供了更严格的一致性模型,禁止出现此相关性问题,并称为sequential consistency.您可以在Java语言规范的§17.4.3和§17.4.5节中找到它.最重要的部分是:
A program is correctly synchronized if and only if all sequentially consistent executions are free of data races. If a program is correctly synchronized,then all executions of the program will appear to be sequentially consistent (§17.4.3).
这意味着,volatile比以前发生的更多.如果用于所有冲突的访问,它会为您提供顺序一致性(§17.4.3).