2017-09-29 18 views
0

私はこのコードについてとても困惑している:なぜSystem.out.printlnはJavaの実行順序に影響しますか?

public class SynchronizedTest implements Runnable { 

private int b = 100; 

public synchronized void test01() throws InterruptedException { 
    b = 1000; 
    Thread.sleep(5000); 
} 

public synchronized void test02() throws InterruptedException { 
    b = 2000; 
    Thread.sleep(2500); 
    //System.out.println("test02 end !"); 
} 

@Override 
public void run() { 
    try { 
     test01(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

public static void main(String[] args) throws InterruptedException { 
    SynchronizedTest test = new SynchronizedTest(); 
    Thread thread01 = new Thread(test); 
    thread01.start(); 
    test.test02(); 
    System.out.println(test.b); 
} 

} 

私は上記のコードで、このコードSystem.out.println("test02 end !");を追加しない場合。

操作結果は印刷1000になりますが、コードを入力すると操作結果が "test02 end!"に変わります。 2000年。

私はなぜ、どのようにそれを説明するのか分からないのですか?

+0

System.out.printline()はスレッドセーフではありません。https://stackoverflow.com/questions/9459657/synchronization-and-system-out-println – User

+0

まだスレッドセーフではありませんか?ソースコードはすぐに追加されました。 public void println(int x){ { print(x); newLine(); } } –

+0

私は問題が実行されていると思う、Athought Soutはスレッドセーフではない、コードに影響はない。 –

答えて

0

これは、コンパイラが命令をスケジューリングする方法とはまったく関係があります。 bの値は変更されていますが、コンパイラはtest02関数を呼び出す前にprint命令をスケジュールしています。

SynchronizedTest test = new SynchronizedTest(); 
Thread thread01 = new Thread(test); 
thread01.start(); 
System.out.println(test.b); 
System.out.println(test.b); 
test.test02(); 
System.out.println(test.b); 

私は上記の順番を試みたが、出力はこれがまた私の引数をサポートしています

100 
1000 
2000 

ました。コンパイラがtest02関数内のテキストを出力しなければならないことを推測し、実行の順序を変更しないので、print文のコメントを外すと、これは起こりません。

しかし、コンパイラが最初のケースで順序を変更する理由はわかりません。

+0

私のコード操作の結果はあなたの...と同じではありません 印刷100,100,2000 .. 私は1000を印刷する方法がないと思うtest02実行時にbacause、SynchronizedTestオブジェクトがロックされているのみtest02最後にtest01があります。総時間は7.5秒です –

+0

私は完全にコンパイラに依存すると思います。私は1000枚印刷しました。これは、コンパイラがどのように構築されたかを知らなくても完全に理解できないものです。 –

関連する問題