簡體   English   中英

為什么 Java 同步線程打印亂序?

[英]Why Java synchronized threads printing out of order?

我正在運行這個 java 線程示例:

public class Locks1 extends Thread {
    private Object lock;
    private int myId;
    public Locks1( Object l, int id ) { 
      lock = l; myId = id; 
    }
    public void run() { 
      synchronized( lock ) {
        for ( int i = 0; i < 3; i++ ) {
          System.out.println( "Thread #" + myId + " is tired" ); 
        try {
          Thread.currentThread().sleep( 10 );
        } catch ( InterruptedException e ){

        } System.out.println("Thread #" + myId + " is rested" );
      }
    }
  }
    public static void main( String args[] ) {
        Integer lock = new Integer( 0 );
        for ( int i = 0; i < 4; i++ ) {
          new Locks1( lock, i ).start(); 
        }
    }
}

我得到了這個結果:

Thread #0 is tired
Thread #0 is rested
Thread #0 is tired
Thread #0 is rested
Thread #0 is tired
Thread #0 is rested
Thread #3 is tired
Thread #3 is rested
Thread #3 is tired
Thread #3 is rested
Thread #3 is tired
Thread #3 is rested
Thread #2 is tired
Thread #2 is rested
Thread #2 is tired
Thread #2 is rested
Thread #2 is tired
Thread #2 is rested
Thread #1 is tired
Thread #1 is rested
Thread #1 is tired
Thread #1 is rested
Thread #1 is tired
Thread #1 is rested

我不明白為什么它按這個順序打印。 誰能幫我理解為什么序列是 0321 而不是 0123?

謝謝

在您的代碼中,第一個問題是鎖資源必須是最終對象,因此如下聲明:

final Integer lock = new Integer( 0 );

由於沒有這種語義,不同的線程可能會鎖定不同的對象,但會在同一對象上運行。

以及對您觀察到的行為的解釋。

雖然目標可能是提高整體性能,但與單線程方法相比,使用多線程總是會帶來一些性能成本。 這些包括與線程之間的協調(鎖定、信令、同步)、增加的上下文切換、線程創建和拆卸以及調度開銷相關的開銷。 ref.ch-11.1

如上所述,與單線程程序相比,鎖定和上下文切換和信號通知與多線程相關。 例如,在您的情況下,您獲得序列“0321”的原因在另一台機器上無法重現。

Thread.start()方法調用系統本地方法start0並且系統分配資源以及線程是否鎖定任何資源(它這樣做)。 由於您的方法需要時間(無論多小)來完成run()方法,因此其他線程正在等待

將代碼更改為此的簡單區別將產生不同的輸出。 因為這引入了處理器恢復和獲取下一個Integer lock線程的時序和調度的差異。 簡而言之,這不是可重復的輸出,並且在 1001 嘗試“可能是”中會有所不同。

 final Integer lock = new Integer( 0 );
 for ( int i = 0; i < 4; i++ ) {
    System.out.println("starting : " + i);
    new Locks1( lock, i ).start();
 }

輸出:

starting : 0
starting : 1
Thread #0 is tired
Thread #0 is rested
Thread #0 is tired
Thread #0 is rested
Thread #0 is tired
Thread #0 is rested
Thread #1 is tired
Thread #1 is rested
Thread #1 is tired
Thread #1 is rested
Thread #1 is tired
Thread #1 is rested
starting : 2
Thread #2 is tired
Thread #2 is rested
Thread #2 is tired
Thread #2 is rested
Thread #2 is tired
Thread #2 is rested
starting : 3
Thread #3 is tired
Thread #3 is rested
Thread #3 is tired
Thread #3 is rested
Thread #3 is tired
Thread #3 is rested

注意:這也可能無法在您的機器中重現。

當多個線程正在等待獲取鎖並且它最終變得可用時,無法保證將選擇哪個線程。 它可以是任何一個。 如果多次執行測試,可能會得到不同的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM