2011-12-14 77 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();