2011-12-14 40 views
0

所以我有以下代碼:Java的synchronized塊,不是所有的線程就會被終止

import java.lang.Thread; 
import java.lang.Integer; 

class MyThread extends Thread { 
private int id; 

MyThread(int i){ 
    id = i; 
    } 

public void run() { 
    while(true){ 
     try{      
      synchronized(Global.lock){ 
       Global.lock.wait(); 
       if(Global.n == 0) {System.out.println(id); Global.lock.notify(); break;} 
       --Global.n; 
       System.out.println("I am thread " + id + "\tn is now " + Global.n); 
       Global.lock.notify(); 
       } 
      } 
     catch(Exception e){break;} 
     } 
    } 
} 

class Global{ 
public static int n; 
public static Object lock = new Object(); 
} 

public class Sync2{ 
public static final void main(String[] sArgs){ 
    int threadNum = Integer.parseInt(sArgs[0]); 
    Global.n = Integer.parseInt(sArgs[1]); 

    MyThread[] threads = new MyThread[threadNum]; 

    for(int i = 0; i < threadNum; ++i){ 
     threads[i] = new MyThread(i); 
     threads[i].start();  
     } 
    synchronized(Global.lock){Global.lock.notify();} 
} 
} 

兩個參數被輸入:一些n以及要創建的線程數。每個線程都會減少n,然後傳遞控制權。當n爲0時,所有線程都應該停止。它似乎迄今爲止工作正常,但唯一的問題是,在大多數情況下,除一個線程外的所有線程都會終止。還有一個掛着。任何想法爲什麼?

是的,這是作業的一部分,這是我迄今爲止所做的(我沒有提供代碼)。我也明確限制使用一個同步塊,只有wait().notify()方法由任務完成。

編輯:改性同步塊一個比特:

synchronized(Global.lock){ 
    Global.lock.notify(); 
    if (Global.n == 0) {break;} 
    if (Global.next != id) {Global.lock.wait(); continue;} 
    --Global.n; 
    System.out.println("I am thread " + id + "\tn is now " + Global.n); 
    Global.next = ++Global.next % Global.threadNum; 
    } 

現在線程在它們被創建的順序嚴格行事。從任務的措辭來看,它很不清楚,但可能是正確的。

+0

你的鎖對象應該是`final`。 – Paul 2011-12-14 05:51:23

+0

你是否必須使用`wait`和`notify`或者他們是否可選?如果你所要做的只是減少n,你可以用`synchronized`來完成。 – Paul 2011-12-14 06:47:51

+0

是的,我明白了。對我來說,就像我實際上必須...仍然不能找出一種方法,使其爲單個工作人員工作。其實沒有人通知... – 2011-12-14 06:59:29

回答

0

您有一個競賽條件。想想單個工作線程會發生什麼。 Global.n設置爲1,然後該線程啓動。它立即進入等待狀態。不過,假設主線程上已經調用了notify()。由於工作線程尚未進入等待狀態,因此不通知。然後,當它最終確實調用wait()時,沒有其他線程可以調用notify(),它永遠處於等待狀態。你需要修正你的邏輯來避免這種競爭條件。

此外,你真的想要一個工作者線程不止一次遞減Global.n?這很容易發生在您的while (true) ...循環中。

編輯 你也有單線程的另一個邏輯問題。假設它進入等待狀態,然後調用main中的notify()。它喚醒工作線程,將Global.n遞減爲0,調用notify(),然後返回等待狀態。問題是notify()沒有喚醒任何其他線程,因爲沒有其他線程要喚醒。所以一個工作者線程將永遠等待。我沒有完全分析它,但類似的情況也可能發生在多個工作線程中。

0

你不應該有一個赤裸的wait()調用,因爲java中的信號量沒有被緩存。 wait()應該總是嵌套在某種

while (condition that you are waiting on) 
    obj.wait();