挥发性背驮式。 这对于visiblity来说足够了吗?

这是关于挥发性的背驮式。 目的:我希望达到轻量级vars visibilty。 a_b_c的一致性并不重要。 我有一堆vars,我不想让它们都变得不稳定。

这段代码是否安全?

class A { public int a, b, c; volatile int sync; public void setup() { a = 2; b = 3; c = 4; } public void sync() { sync++; } } final static A aaa = new A(); Thread0: aaa.setup(); end Thread1: for(;;) {aaa.sync(); logic with aaa.a, aaa.b, aaa.c} Thread2: for(;;) {aaa.sync(); logic with aaa.a, aaa.b, aaa.c} 

Java Memory Model定义了before-before关系,它具有以下属性(以及其他属性):

  • “线程中的每个操作都发生在 – 在程序顺序中稍后出现的该线程中的每个操作之前”(程序顺序规则)
  • “对一个易失性字段的写入发生 – 在每次后续读取同一个volatile之前”(volatile变量规则)

这两个属性以及先发生关系的传递性意味着可见性保证OP以下列方式寻求:

  1. 对线程1的写入发生在线程1(程序顺序规则)中对sync()的调用中的sync()写入之前
  2. 在线程1中对sync()的调用中的写入sync 发生在线程2中的sync调用中的读取sync 之前 (易失性变量规则)。
  3. 在线程2中对sync()的调用中的sync()读取发生在从线程2(程序顺序规则)中读取之前

这意味着问题的答案是肯定的,即在线程1和2中的每次迭代中对sync()的调用确保了对abc更改对其他线程的可见性。 请注意,这只能确保可见性。 不存在互斥保证,因此可能违反绑定abc所有不变量。

另请参阅Java理论与实践:修复Java内存模型,第2部分 。 特别是“挥发性新保证”一节

在新的内存模型下,当线程A写入易失性变量V,并且线程B从V读取时,保证在写入V时A可见的任何变量值现在对B可见。

增加线程之间的值绝不是线程安全的,只是volatile 。 这只能确保每个线程获得最新值,而不是增量是primefaces的,因为在汇编程序级别,++实际上是几个可以交错的指令。

您应该使用AtomicInteger进行快速primefaces增量。

编辑 :再次阅读你需要的是一个记忆围栏。 Java没有内存栅栏指令,但您可以使用锁定内存栅栏“副作用”。 在这种情况下,声明同步方法已同步以引入隐式栅栏:

 void synchronized sync() { sync++; } 

来自javadoc:

监视器的解锁(同步块或方法退出)发生在同一监视器的每个后续锁定(同步块或方法入口)之前。 并且因为发生在之前的关系是可传递的,所以在解锁之前线程的所有动作都发生在任何线程锁定该监视器之后的所有动作之前。

对易失性字段的写入发生在每次后续读取该相同字段之前。 易失性字段的写入和读取具有与进入和退出监视器类似的内存一致性效果,但不需要互斥锁定。

所以我认为在这种情况下写入volatile var并不等同于同步,并且它不保证在Thread1到Thread2的更改顺序和可见性之前发生

模式通常是这样的。

 public void setup() { a = 2; b = 3; c = 4; sync(); } 

但是,虽然这可以保证其他线程会看到此更改,但其他线程可以看到不完整的更改。 例如, Thread2可能会看到a = 2,b = 3,c = 0.或甚至可能a = 2,b = 0,c = 4;

在阅读器上使用sync()并没有多大帮助。

您根本不需要手动同步,只需使用自动同步的数据结构,如java.util.concurrent.atomic.AtomicInteger

您也可以使sync()方法synchronized