2

次の C# コードでは、t1 は常に (私が試したときは) 終了します。

class MainClass
{
    static void DoExperiment ()
    {
        int value = 0;

        Thread t1 = new Thread (() => {
            Console.WriteLine ("T one is running now");
            while (value == 0) {
                //do nothing
            }
            Console.WriteLine ("T one is done now");
        });

        Thread t2 = new Thread (() => {
            Console.WriteLine ("T two is running now");
            Thread.Sleep (1000);
            value = 1;
            Console.WriteLine ("T two changed value to 1");
            Console.WriteLine ("T two is done now");
        });

        t1.Start ();
        t2.Start ();

        t1.Join ();
        t1.Join ();
    }

    public static void Main (string[] args)
    {
        for (int i=0; i<10; i++) {
            DoExperiment ();
            Console.WriteLine ("------------------------");
        }
    }
} 

しかし、非常によく似た Java コードでは、t1 は (私が試したときは) 終了しません。

public class MainClass {
static class Experiment {
    private int value = 0;

    public void doExperiment() throws InterruptedException {

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {

                System.out.println("T one is running now");
                while (value == 0) {
                    //do nothing
                }
                System.out.println("T one is done now");
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("T two is running now");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                value = 1;
                System.out.println("T two changed value to 1");
                System.out.println("T two is done now");
            }
        }
        );

        t1.start();
        t2.start();

        t1.join();
        t1.join();
    }
}


public static void main(String[] args) throws InterruptedException {
    for (int i = 0; i < 10; i++) {
        new Experiment().doExperiment();
        System.out.println("------------------------");
    }
}

}

何故ですか?

4

2 に答える 2

3

C# でどうなるかはわかりませんが、Java で起こるのはJVM最適化です。の値はループvalue内で変更されず、はそれを認識し、テストをスキップしてバイト コードを次のように変更します。whileJVM

while (true) {
    // do nothing
}

これを Java で修正するには、次のように宣言する必要がありvalueますvolatile

private volatile int value = 0;

これにより、 はこのループをJVM最適化せず、各反復の開始時にの実際の値をチェックします。whilevalue

于 2013-10-31T15:38:00.447 に答える