util - java8 multi thread




在這個例子中是否有競爭條件? 如果是的話,怎麼可能避免呢? (2)

是的 - 這是一個什麼樣的線程首先進入哪個同步塊的競賽。 對於比賽的大多數情況,輸出和答案將是相同的。 但是,其中一個方案將陷入僵局:

  1. 主要開始調用b.start()並立即調度。
  2. 線程B啟動,進入synchronized,調用notify()。
  3. 主進入其同步塊,調用wait()

在這種情況下,main將永遠等待,因為線程b在主要阻塞wait()之前調用notify。

也就是說,這是不太可能的,但是在所有的線程中,你都應該得出這樣的結論,那就是在最糟糕的時候。

我正在看一些通知/等待的例子,並遇到這一個。 我明白一個同步塊本質上定義了一個關鍵部分,但是這不是一個競爭條件? 沒有指定首先輸入哪個同步塊。

public class ThreadA {
    public static void main(String[] args){
        ThreadB b = new ThreadB();
        b.start();

        synchronized(b){
            try{
                System.out.println("Waiting for b to complete...");
                b.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }

        System.out.println("Total is: " + b.total);
        }
    }
}

class ThreadB extends Thread {
    int total;

    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            notify();
        }
    }
}

每個網站的輸出:

等待b完成...

總計是:4950


是的,這是一個競爭條件。 沒有任何東西阻止ThreadB啟動,輸入其運行方法,並且在ThreadA進入其同步塊之前同步自己(因此無限期地等待)。 然而,考慮到新線程開始執行的時間,這是不太可能發生的。

處理這種情況的最簡單和最推薦的方式是不要編寫自己的實現,而是選擇使用由Executor提供的可調用/未來版本。

為了解決這個特殊的情況沒有遵循標準:

  • 在ThreadB的同步塊的末尾設置布爾值“已完成”值。
  • 如果在進入同步塊後布爾型“已完成”為真,則不應該調用wait。




synchronized