揮発性フィールドと非揮発性フィールドが混在している場合の揮発性フィールドの事前発生動作を理解しようとしています。
1 つの WriteThread と 5 つの ReadThreads があり、SharedObject を更新/読み取るとします。
ReadThreadswaitToBeStopped()
は最初からメソッドを呼び出し、WriteThread はstop()
1 秒後にメソッドを呼び出します。
public class SharedObject {
volatile boolean stopRequested = false;
int a = 0, b = 0, c = 0;
int d = 0, e = 0, f = 0;
// WriteThread calls this method
public void stop() {
a = 1;
b = 2;
c = 3;
stopRequested = true;
a = 4;
b = 5;
c = 6;
d = 7;
e = 8;
f = 9;
}
// ReadThread calls this method
public void waitToBeStopped() throws Exception {
while(!stopRequested) {
}
System.out.println("Stopped now.");
System.out.println(a + " " + b + " " + c + " " + d + " " + e + " " + f);
}
}
このプログラムが終了すると、出力は次のようになります。100 以上の ReadThreads を試しても、結果は常に同じです。
Stopped now.
Stopped now.
Stopped now.
Stopped now.
Stopped now.
4 5 6 7 8 9
4 5 6 7 8 9
4 5 6 7 8 9
4 5 6 7 8 9
4 5 6 7 8 9
Q1. これが常に1,2,3,0,0,0ではなく4,5,6,7,8,9を返す理由を誰かが説明できますか?
事前発生関係についての私の理解は、次のようなものでした。
- WriteThread の書き込みは、WriteThread の書き込みの
a=1,b=2,c=3
前に発生します。stopRequested
- WriteThread の書き込みは、WriteThread の書き込みの
stopRequested
前に発生します。a=4,b=5,c=6,d=7,e=8,f=9
- WriteThread の書き込みは、ReadThread の読み取りの
stopRequested
前に発生しますstopRequested
- ReadThread 読み取りは、 ReadThread 読み取りの
stopRequested
前に発生しますa,b,c,d,e,f
これらの 4 つのステートメントから、このようなステートメントを導き出すことはできません...
- WriteThread の書き込みは、ReadThread の読み取りの
a=4,b=5,c=6,d=7,e=8,f=9
前に発生しますa,b,c,d,e,f
役立つ場合は、コードの他の部分を次に示します。
public class App {
public static void main(String[] args) throws Exception {
SharedObject sharedObject = new SharedObject();
for(int i =0 ; i < 5; i++) {
Runnable rThread = new ReadThread(sharedObject);
new Thread(rThread).start();
}
Runnable wThread = new WriteThread(sharedObject);
new Thread(wThread).start();
}
}
public class WriteThread implements Runnable {
private SharedObject sharedObject;
public WriteThread(SharedObject sharedObject) {
this.sharedObject = sharedObject;
}
public void run() {
try {
TimeUnit.SECONDS.sleep(1);
sharedObject.stop();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class ReadThread implements Runnable {
private SharedObject sharedObject;
public ReadThread(SharedObject sharedObject) {
this.sharedObject = sharedObject;
}
public void run() {
try {
sharedObject.waitToBeStopped();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}