我有兴趣在不使用sun.misc.Unsafe
的情况下触发一个完整的内存围栏。
下面的Java代码是否会触发一个满内存围栏?
public final class Foo {
public void bar() {
// Before memory fence?
synchronized(this) {
// After memory fence?
}
}
}
以下Java代码是否也触发满内存围栏?
public final class Foo {
private final Object monitor = new Object();
public void bar() {
// Before memory fence?
synchronized(monitor) {
// After memory fence?
}
}
}
- 参考:Java 8 Unsafe:xxxFence()指令
- 参考编号:http://openjdk.java.net/jeps/171
如果您想手动触发一个完整的围栏,您需要查看VarHandle。它有各种各样的栅栏。
纯粹依靠同步区块或挥发物进行围栏行为是非常不可靠的。
例如:
int a=0
thread1:
a=1
synchronized(this){}
thread2:
synchronized(this){}
r1=a
"a"上存在数据争用,因为在线程1更新a=1之后,在释放锁之前,可以读取"a=1"。因此,没有与连接a的写入和1的读取的边缘同步。
JVM可以自由地生成所有可能和有效执行的子集,并且它可以选择只生成"a"保持为零并且永远看不到新值的执行(因为存在数据竞争)。所以没有考虑到整个围栏。
您想要实现什么。您只是想阻止"之前"one_answers"之后"操作的重新排序吗?你需要你的操作是原子的吗?
要回答"是"的问题,锁定将具有与全内存围栏相同的效果,甚至更多。它将确保您的Before和After操作不会被重新订购。它还将确保同步块中的所有写入对其他线程可见。此外,您在持有锁时完成的所有操作都将以原子方式发生。仅仅增加一个完整的围栏是不会实现的。
在java中触发完全隔离的另一种方法是写入易失性变量。