2016-07-24 107 views
0

簡而言之,我想知道這是否會改變行爲。我假設是的,因爲調用someMethod()會鎖定整個對象,而不是隻是列表對象?但我仍然對這個同步的東西很陌生,所以我想要一些更受教育的反饋。從同步塊調用此同步方法可以嗎?

的面前:

public void run() { 
    int i = 0; 

    while (!end) { 
     synchronized (list) { 
      while (list.size() == i) { 
       try { 
        list.wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 

的經過:

public void run() { 
    int i = 0; 

    while (!end) { 
     synchronized (list) { 
      while (list.size() == i) { 
       someMethod(); 
      } 
     } 
    } 
} 

public synchronized void someMethod() { 
    try { 
     list.wait(); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

回答

2

你是正確的 - 新的代碼得到了不同的語義,爲someMethod()確實在它被調用該命令的情況下同步(因此,該同步與list上的同步完全無關)。但是,撥打someMethod()的電話將在list上的監視器被保持時發生,因此對的撥打對list是「同等線程安全」。

另一方面,您現在已經介紹了多個線程同時直接呼叫someMethod()的可能性。由於對象本身的額外同步,您還引入了一個(可能不必要的)與其他線程發生死鎖的可能性。我會推薦這個代替:

public void someMethod() { 
    synchronized (list) { 
     try { 
      list.wait(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

此方法現在無論是個人使用,通過run()被稱爲安全 - 請注意,它是安全的,你已經在同步對象上同步;線程不會阻塞自己。

+0

欣賞它,謝謝! – Badger

2

隨着syncronized你不真的'鎖定'一個對象。您只需確保在同一個特定對象上同步同步的訪問權限是「鎖定」的。

同步方法正在this上同步。

這意味着,如果某個對象list上輸入syncronized塊,你可以在第一


有些東西叫syncronized方法沒有問題加以考慮:

此代碼沒有按」 t產生死鎖:

public void foo() { 
    synchronized (this) { 
     someMethod(); 
    } 
} 

public synchronized void someMethod() { 
    // ... 
} 

因爲你已經有了「鎖定」this ,但是這個:

public void foo() { 
    synchronized (list) { 
     someMethod(); 
    } 
} 

public synchronized void someMethod() { 
    // ... 
} 

可能會產生與其他線程的死鎖!如果您在另一個​​部分輸入​​部分,您必須非常小心。