JAVA使用Condition时中断的一个疑问?

问题描述

在使用Condition进行线程的挂起和唤醒的时候,我经常见到以下的使用方法
Thread1调用Await()方法等待Thread2的Signal唤醒,为了避免长时间的等待,又加了超时的限制,所以Thread1通常写成Condition.await(long,TimeUnit)。但是事实真的是在超时之后,Condition就会返回吗?

问题出现的环境背景及自己尝试过哪些方法

我翻看了一下相关的源码,发现并不是这个样子的。可以通过以下的代码来检测

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)

public class TestConditionAwait {

    private static ReentrantLock lock = new ReentrantLock();

    private static Logger Log = LoggerFactory.getLogger(TestConditionAwait.class);

    public static void main(String[] args) throws InterruptedException {
        final Condition condition = lock.newCondition();
        final Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                try {
                    Thread.currentThread().setName("ConditionAwait-Thread-");
                    Log.error(Thread.currentThread().getName() + " beforeAwaitTime:" + System.currentTimeMillis());
                    condition.await(5000, TimeUnit.MILLISECONDS);
                } catch (InterruptedException e) {
                    Log.error(Thread.currentThread().getName() + " finishAwaitTime:" + System.currentTimeMillis());
                }finally {
                    lock.unlock();
                    Log.error(Thread.currentThread().getName() + " unlockTime:" + System.currentTimeMillis());
                }

            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                Thread.currentThread().setName("ConditionSignal-Thread-");
                try{
                    Log.error(Thread.currentThread().getName() + " getLockTime:" + System.currentTimeMillis());
                    thread1.interrupt();
                    lock.lock();
                    long currentTime = System.currentTimeMillis();
                    while (System.currentTimeMillis() - currentTime < 8000){

                    }
                    condition.signal();
                    Log.error(Thread.currentThread().getName() + " signalTime:" + System.currentTimeMillis());
                }catch (Exception e){

                }finally {
                    lock.unlock();
                    Log.error(Thread.currentThread().getName() + " unlockTime:" + System.currentTimeMillis());
                }
            }
        });
        thread1.start();
        Thread.sleep(50);
        thread2.start();
    }
}

你期待的结果是什么?实际看到的错误信息又是什么?

阅读 1.5k
1 个回答

你代码的结果是这样来的,thread1在await后放弃了锁,thread2获得锁并开始循环,5000ms后,thread1从条件变量等待队列里面被唤醒,此时thread1要重新获得锁才能继续执行下去,但是锁被thread2占用,所以不得不等到thread2释放锁之后,也就是8000ms之后才能继续执行。

thread1从条件变量等待队列中被超时唤醒后又进入了锁等待队列。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题