簡體   English   中英

同步塊程序結果與同步方法不同

[英]Sysnchronized block program results are different from synchronized method

我已經通過鎖定.class在同步塊上編寫了一個程序,並且我的程序正在逐線程執行。 但是,當我使用同步方法編寫相同的代碼時,輸​​出完全不同。

同步塊程序如下:

public class SyncBlock {
    public static void main(String[] args) {
        final Thread t1 = new SimpleThread("First Thread");
        final Thread t2 = new SimpleThread("Second Thread");
        t1.start();
        t2.start();
    }
}

class SimpleThread extends Thread {
    public SimpleThread(String str) {
        super(str);
    }

    public void run() {
        synchronized (SyncBlock.class) {
            for (int i = 0; i < 5; i++) {
                System.out.println(getName() + " says " + i);
                try {
                    sleep((long) (Math.random() * 1000));
                } catch (InterruptedException e) {
                }
            }
            System.out.println(getName() + " is done.");
        }
    }
}

輸出是:

First Thread says 0
First Thread says 1
First Thread says 2
First Thread says 3
First Thread says 4
First Thread is done.
Second Thread says 0
Second Thread says 1
Second Thread says 2
Second Thread says 3
Second Thread says 4
Second Thread is done.

現在我正在使用同步方法使用相同的程序。 但是它的行為有所不同。 您能否解釋一下兩者的行為是否不同,或者是否有使用同步塊和同步方法獲得相同輸出的解決方案?

使用同步方法:

現在同步運行方法並替換以下代碼:

public synchronized void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(getName() + " says " + i);
                try {
                    sleep((long) (Math.random() * 1000));
                } catch (InterruptedException e) {
                }
            }
            System.out.println(getName() + " is done.");
}

這里的輸出是不同的:

First Thread says 0
Second Thread says 0
Second Thread says 1
First Thread says 1
First Thread says 2
Second Thread says 2
First Thread says 3
Second Thread says 3
First Thread says 4
First Thread is done.
Second Thread says 4
Second Thread is done.

synchronized塊中,您正在鎖定類對象,當一個對象調用它時,該類對象將在其他對象上鎖定run方法的執行。 但是,當您synchronized運行方法時,您將鎖定對象而不是類,因此它將不會阻止另一個線程在另一個對象上執行相同的方法。 因此,兩個線程並行執行。

如果要實現與synchronized塊相同的執行,則可以有一個synchronized static方法,該方法執行正在運行的步驟並從run方法中調用它

當您使用: synchronized (SyncBlock.class) ,您的代碼可以正常工作,因為您鎖定了SyncBlock類,因此其他線程無法訪問SyncBlock Object類,直到第一個線程釋放它。

在第二種情況下,您鎖定了SimpleThread的當前實例(此),兩個線程的鎖定將不同(您鎖定了SimpleThread實例本身)。 因此,鎖本身是無效的,JVM也可能會刪除同步代碼(從jdk6 U23-引入轉義分析來優化此類事情)

如果是同步塊,則說第一個線程先進入

synchronized (SyncBlock.class) {-->  // here First thread takes the lock now  no other thread can enter 

現在,當第一個線程到達此處

  System.out.println(getName() + " is done.");
    } --->  here First thread releases the lock  . So this gives chance to other thread which are waiting for this lock . so in ur case Second thread takes it and then executes it and when it reaches here it will release and then again other thread can take over. Note  : This behavior is not definite 

線程可以任何方式執行取決於CPU調度策略

在同步方法中發生的事情是,一旦一個線程進入該方法,它將完成其任務,然后釋放鎖。在另一個線程獲得執行機會之后。

另請注意, 睡眠不會釋放LOCK 在那個階段線程處於等待狀態

這里沒有其他答案是錯誤的,但是它們都沒有真正說明問題的核心。

當您編寫synchronized ,您的代碼將在一個對象上同步,並且JVM保證不能在同一對象上同時同步兩個線程。

在第一個示例中,SimpleThread.run()方法在唯一的SyncBlock類對象上同步。 這樣可以防止兩個線程同時進入run(),因為它們都試圖在同一個對象上進行同步:只有一個SyncBlock類對象。

在第二個示例中,SimpleThread.run()方法在this同步。 並不妨礙兩個線程在同一時間進入運行(),因為兩個線程同步在兩個不同的對象:創建SimpleThread的兩個實例。

暫無
暫無

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

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