1

揮発性フィールドと非揮発性フィールドが混在している場合の揮発性フィールドの事前発生動作を理解しようとしています。

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();
        }
    }   
}

4

1 に答える 1