2013-02-14 34 views
1

试图行使我对Java并发的理解,这里的问题: 可以有多个线程运行方法A和只有一个线程运行方法B(可以说当A()运行所以在第10次时,该线程将运行方法B.发生这种情况时,它必须阻止运行A的线程并允许已经运行A的线程在运行B的其余部分之前完成。另外,A中的线程应该“T等待本身Java:防止在这个例子中的死锁

编辑:所有线程都在第一个开始,还有就是检查时运行B.

我尝试到目前为止看起来像这样一个外部方法:

volatile Boolean lock = false; //false = threads in method A allowed to run, thread in method B otherwise 
volatile Integer countOfA = 0; 

void A(){ 
    boolean continue = false; 
    synchronized(lock){ 
    if(lock == true){ //there is a thread in B, block threads in A 
     lock.wait(); 

     increaseCountOfA(); 
     //do work 
     decreaseCountOfA(); 

     if(countOfA == 0){ //this was the last thread that ran with lock 
      lock = true; 
      lock.notify(); //only the thread in B should be waiting on this 
     } 
     }else{ 
     continue = true; 
     } 
    } 

    if(continue){ 
     increaseCountOfA(); 
     //do work; 
     decreaseCountOfA(); 
    } 
} 

void B(){ 
    synchronized(lock){ 
    if(lock == false){ 
     lock.wait(); 
     if(countOfA > 0){ 
      countOfA.wait(); 
     } 
     //do work; 
     lock = false; 
     lock.notifyAll(); 
    } 
    } 
} 

void increaseCountOfA(){ 
    synchronized(countOfA){ 
    countOfA++; 
    } 
} 

void decreaseCountOfA(){ 
    synchronized(countOfA){ 
    countOfA--; 
    } 
} 

当它运行时,它挂起。我怀疑有一个死锁,我也不知道这个问题需要多少级别的同步。这可以用一个级别完成吗?

+1

纠正我,如果我错了,但我不用这个代码的可伸缩'锁'永远得到被设置为真,所以可能你的所有线程都在等待它。 – 2013-02-14 03:41:33

+0

是的,你是对的。将其初始化为true,但其行为仍未更改。 – user1203349 2013-02-14 03:49:57

+0

@Belov其实,锁定首先是假的,以允许线程首先在A中工作,注意到A()中的else。 – user1203349 2013-02-14 04:00:33

回答

0

当你做synchronized(lock)你正在同步lock所指的对象,而不是变量。您可能需要一个独立的锁对象,其值不会更改。或者,您可以考虑使用更高级别的并发类,如Semaphore

在这种情况下,您有一个线程在等待Boolean.TRUE,另一个线程在Boolean.FALSE上发布通知。

+0

不会有锁的常量对象,因为它们都是同步的,所以A中的线程会按顺序执行?那些同步块可能不应该是那么大的开始。 – user1203349 2013-02-14 04:21:25

+0

您的所有线程A都将等待锁定。由于'wait()'释放监视器,只要一个线程等待,其他人可以自由地进入'synchronized'块。那么'notify()'永远不会被调用,因为所有的线程A都被阻塞,并且线程B只有在'lock'有些错误时才调用'notify()'。 – 2013-02-14 04:27:24