首页新闻找找看学习计划

关于java多线程中的await和signalAll的使用问题

0
悬赏园豆:10 [已解决问题] 解决于 2013-12-29 11:03

package test.synchornize;

import java.util.concurrent.locks.*;

class runab implements Runnable{
 boolean x = true;
 static Lock lock = new ReentrantLock();
 static Condition con1 = lock.newCondition();
 static Condition con2 = lock.newCondition();
 runab(boolean x){
  this.x = x;
 }
 public void run() {
  lock.lock();
  try {
   System.out.println("Start---" + Thread.currentThread().getName());
   if(x) {
    x = false;
    try {con1.await();con2.await();} catch (InterruptedException e) {}
   }
   System.out.println("End---" + Thread.currentThread().getName());
  } finally {

   con2.signalAll();
   con1.signalAll();
   lock.unlock();
  }
 }
}

public class showLock {

 public static void main(String[] args) {
  runab rab = new runab(true);
  runab rab1 = new runab(false);
  Thread th = new Thread(rab);
  Thread th1 = new Thread(rab1);
  th.start();
  try {
   Thread.sleep(100);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  th1.start();
  
 }

}

 

请问finally里面怎样写才能,让线程th继续下去呢?(即让程序最后一行输出

“End---Thread-0”)

剑握在手的主页 剑握在手 | 初学一级 | 园豆:57
提问于:2013-11-13 15:25
< >
分享
最佳答案
1

呵,你这怎么写线程th都执行不下去啊,自己把自己锁死了。con1.await()和con2.await()是释放锁,线程进入阻塞状态并等待其他线程唤醒,finally根本就不会执行,那必然不会唤醒。你这con1和con2就不应该是对象内的局部变量,应该是线程间的共享变量,才能在自己等待的时候,被其他线程唤醒。

收获园豆:10
孟衡 | 菜鸟二级 |园豆:228 | 2013-12-28 18:00

我定义的static Condition,static不是可以共享吗?

剑握在手 | 园豆:57 (初学一级) | 2013-12-28 21:12

@剑握在手: 不好意思,之前没看清楚,很少有你这么写的,包括runab的类名竟然是小写开头。我拷贝了你的代码试验了一下,没有输出“End---Thread-0”的原因是这样的:当线程th运行的时候,在con1.await()处等待并释放锁,注意此时并没有运行con2.await()。线程th1运行时由于x为false所以直接进入finally块,首先唤醒阻塞在con2上的线程,但此时并没有线程阻塞在con2上;然后唤醒阻塞在con1上的线程即线程th,等走完lock.unlock()之后,线程th开始接着con1.await()后面执行,也就是con2.await(),再次将自己阻塞,而此时不再有其他线程来唤醒它了。

我不太清楚你的源代码是要解决什么问题,所以没法提出合适的修改意见,如果仅仅是个实验,那明白上面所说的就够了,要使“End---Thread-0”打印出来,在main函数最后再加上一个运行rab1的线程即可,如下(增加了15-22行):

 1 public static void main(String[] args) {
 2         Runab rab = new Runab(true);
 3         Runab rab1 = new Runab(false);
 4         Thread th = new Thread(rab);
 5         Thread th1 = new Thread(rab1);
 6         th.start();
 7         try {
 8             Thread.sleep(100);
 9         } catch (InterruptedException e) {
10             // TODO Auto-generated catch block
11             e.printStackTrace();
12         }
13         th1.start();
14         
15         try {
16             Thread.sleep(100);
17         } catch (InterruptedException e) {
18             // TODO Auto-generated catch block
19             e.printStackTrace();
20         }
21         Thread th2=new Thread(rab1);
22         th2.start();
23     }
孟衡 | 园豆:228 (菜鸟二级) | 2013-12-29 10:48

@孟衡: 正是这个原因,非常感谢你的热心帮助。

剑握在手 | 园豆:57 (初学一级) | 2013-12-29 11:03
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册