[英]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.