在Java中发生在机制之前
我有一个关于Java中before机制的问题。以下是一个例子:在Java中发生在机制之前,java,multithreading,volatile,java-memory-model,Java,Multithreading,Volatile,Java Memory Model,我有一个关于Java中before机制的问题。以下是一个例子: public class MyThread extends Thread { int a = 0; volatile int b = 0; public void run() { try { Thread.sleep(500); } catch (InterruptedException e) {
public class MyThread extends Thread {
int a = 0;
volatile int b = 0;
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
read();
}
public void write(int a, int b) {
this.a = a;
this.b = b;
}
public void read() {
System.out.println(a + " " + b);
}
}
这是以前发生过的一个明显的例子,正如我所知,这是足够安全的a
将正确地获取新值,因为它位于b
的初始化之前。但重新订购是否意味着安全得不到保证?我说的是:
public void write(int a, int b) {
this.b = b;
this.a = a;//might not work? isn't it?
}
UPD主线程:
public class Main {
public static void main(String[] args) throws InterruptedException {
MyThread t = new MyThread();
t.start();
t.write(1, 2);
}
}
将
b
设置为volatile
并在将值设置为a
后将write
设置为b
,可确保:
a
之前读取b
,则a
的值不会早于先前写入b
时的值b
和读取b
充当同步点或围栏,这意味着在写入b
之前写入a
的内容将在读取b
之后可读(如果a
被写入多次,则以下写入可能可见,也可能不可见)
但是,您的代码并不像现在这样安全。在read
中,您有以下表达式:
a + " " + b
在Java中,。这意味着,a
将在b
之前求值。因此,完全有可能读取a
将看到一个旧值a
,而读取b
将看到一个新值b
。如果您在a
之前读取了b
,则发生在关系之前n在b
之间的写入和读取本应包括对a
的写入和对a
的读取。现在,它没有
至于write
中的重新排序操作,这将明显消除b
的排序保证对a
的操作过度的影响,即使read
先读取b
然后读取a
要将事物形象化,只有b
是volatile
:
当前的代码不保证对操作的顺序-
write a read a
write b --> happens before --> read b
使用给定的读取重新排序write
也不会排序a
-
read a
write b --> happens before --> read b
write a
即使给定的读取
是固定的,a
也不会被b
-
write b --> happens before --> read b
write a read a
唯一安全的方法是保持当前的写入
,并修复读取
-
write a
write b --> happens before --> read b
read a
你能添加包含start()调用的代码吗?我不能完全理解你在这里的要求