2011-04-27 135 views
70

如果同步方法調用另一個同步方法,它是否線程安全?從另一個同步方法調用同步方法是否安全?

void synchronized method1() { 
    method2() 
} 

void synchronized method2() { 
} 
+0

這篇文章有幫助嗎,或者你困惑在哪裏? http://kalyanchakravarthy.net/?p=413 – 2011-04-27 02:23:18

+0

是的 - 您實際上並不需要將method2標記爲synchronized,假定它只在上面給出的上下文中調用。 – debracey 2011-04-27 02:23:52

+3

另外,它是否是線程安全的將取決於兩種方法中發生的情況。例如,如果他們調用非線程安全列表,那麼如果其他線程可以修改該集合,則它們可能不是線程安全的。 – 2011-04-27 02:24:20

回答

88

是的,當你方法標記爲​​,那麼你真的這樣做:

void method1() { 
    synchronized (this) { 
     method2() 
    } 
} 

void method2() { 
    synchronized (this) { 
    } 
} 

當線程調用進入從方法1方法2,那麼將確保其持有的鎖this,它已經,然後它可以通過。

當線程直接進入method1或method2時,它會阻塞,直到它可以獲得鎖(this),然後它將進入。

正如詹姆斯布萊克在評論中指出的那樣,你必須知道你在方法體內做了什麼。

private final List<T> data = new ArrayList<T>(); 

public synchronized void method1() { 
    for (T item : data) { 
     // .. 
    } 
} 

public void method3() { 
    data.clear(); 
} 

突然,因爲你是在你的未來尋找一個ConcurrentModificationException因爲method3是不同步的它不是線程安全的,因此可以通過線程A,而線程B在method1工作進行調用。

+0

我試圖回答一個幾乎與此處提問相同的問題。這是2個可能的答案(其他2個說不會運行),這是正確的? C. \t該代碼將運行,但有潛在的死鎖情況 D. \t代碼將運行良好,因爲Java提供了可重入同步,使線程可以多次獲取相同的鎖-----我猜測它是D,但也許潛在的死鎖情況依賴於方法體? – 2015-05-10 01:35:26

+0

@ user3140993這裏的代碼沒有死鎖的機會。 'method3'顯示不安全的線程操作,但是您關注的是重入同步。 – pickypg 2015-07-28 02:49:48

1

從Java教程網站http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

  1. 這是不可能的同一對象的同步方法交錯兩個調用。當一個線程正在執行一個對象的同步方法時,所有其他線程調用同一對象的同步方法塊(掛起執行),直到第一個線程完成對象。

  2. 當一個同步方法退出時,它會自動與同一對象的任何後續調用同步方法建立一個前後關係。這保證了更改對象的狀態是可見的所有線程

所以Java將確保如果兩個線程都在執行同樣的方法,該方法不會consurrently但接二連三執行。

但是你需要知道的活躍度的問題,http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html

而且也不管你是鎖定uncessarily,原因在您使用這個,它鎖定了整個對象的代碼,如果你的對象只需要同步訪問一個變量,你應該只鎖定該變量。

+0

@Stephen Lee - 你不能鎖定一個變量。然後你說'synchronized(this.someVar)'你正在查看引用保存在'someVar'中的對象。區別非常重要。 – 2011-04-27 02:43:41

4

是一種用synchronized調用另一個同步方法線程安全的方法。

一般來說,這是不可能說的。它取決於方法的作用,以及同一類和其他類中的其他方法。

但是,我們可以確定,由不同線程創建的同一個對象上的method1和method2調用不會同時執行。根據這些方法的作用,這個可能是就足以說這個類對於這些方法是線程安全的。