[英]Java: synchronize keyword doesn't block object on different thread
public class SynchronizeTest {
public synchronized void methodA() {
System.out.println("calling method a ...");
sleep(2000);
System.out.println("ending method a");
}
public void methodC() {
System.out.println("calling method C");
new Thread(new Runnable() {
@Override
public void run() {
methodA();
}
}).start();
sleep(100);
System.out.println("end method C");
}
public static void main(String[] args) {
new SynchronizeTest().methodC();
}
static void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
起初,我猜是因為我synchronize
方法A,這意味着整個對象將被鎖定,直到該方法完成為止。 所以答案應該是:
calling method C
calling method a
ending method a
ending method C
但是事實證明,結果是這樣的:
calling method C
calling method A
ending method C
ending method A
這意味着methodA
不會像我猜的那樣鎖定對象。 請告訴我為什么。
在實例方法上使用synchronized
關鍵字時,這意味着該對象上的方法當時只能由一個線程調用。
這並不意味着對對象的所有方法進行任何形式的鎖定,即可以在該方法的調用期間調用其他實例方法-當您在執行操作時異步調用它時,也更容易。
既然你是你的線程內調用它methodC
,並在睡眠時間methodA
比結束前的一個更大的methodC
,您的電流輸出是非常可能發生的每一次。
這是相關的文檔報價(請參閱此處的頁面):
使得方法同步具有兩個作用:
首先,不可能在同一對象上兩次調用同步方法。 當一個線程正在執行對象的同步方法時,所有其他調用同一對象塊的同步方法的線程(掛起執行),直到第一個線程對該對象完成。
其次,當同步方法退出時,它會自動建立與先后發生的關系,並隨后對同一對象調用同步方法。 這保證了對象狀態的更改對所有線程都是可見的。
注意
您可能需要join
調用methodA
的線程,以確保在執行methodC
的最后一條語句之前終止其執行。
首先,您有2個線程1)main和2)您創建的線程(假設為thread1)。 現在發生的事情是使methodA同步,因此當線程1到達那里時它將保留在該方法中並嘗試完成執行,但同時主線程可以進一步處理並打印最后的C語句。因為您在方法中添加了sleep調用,這導致thread1睡眠2秒。 所以輸出將是C(主線程),a(您的線程),C(主線程),a(您的線程)
請閱讀以下內容: https : //docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html如前所述,不可能對同一對象的兩次同步方法調用進行交織。 當一個線程正在執行對象的同步方法時,所有其他調用同一對象塊的同步方法的線程(掛起執行),直到第一個線程對該對象完成。 這意味着該對象將被其他同步方法鎖定。 同步methodC也不是一個好主意。 它將為您提供以下輸出:調用方法C /調用方法a /結束方法a /結束方法C。為了獲得所需的輸出,可以使用以下代碼:
public class SynchronizeTest implements Runnable{
public synchronized void methodA() throws InterruptedException {
System.out.println("calling method a ...");
Thread.sleep(2000);
System.out.println("ending method a");
this.notify();
}
public synchronized void methodC() throws InterruptedException {
System.out.println("calling method C");
new Thread(new Runnable() {
@Override
public void run() {
methodA();
}
}).start();
this.wait();
System.out.println("end method C");
}
public static void main(String[] args) throws InterruptedException {
new Test().methodC();
}
@Override
public void run() {
// TODO Auto-generated method stub
}
}
關鍵字synchronized
意味着防止不同線程使用相同變量時發生的錯誤。 鎖定線程根本沒有任何意義,因為您可以隨后調用方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.