zoukankan      html  css  js  c++  java
  • ReentrantLock的Condition使用问题

    这几天在网上看到了一个面试经常会问到的题目: 3个线程依次打印数字。我就用ReentrantLock+Condition写了一个,代码如下:

    /**
     * @auther panfei
     * @date 2018/2/8
     */
    public class ConditionTest implements Runnable {
        private final static ReentrantLock lock = new ReentrantLock();
        private final static Condition condition = lock.newCondition();
        private static int count = 0;
        private int privilege;
        private final static int THREADNUM = 3;
    
        public ConditionTest(int privilege) {
            this.privilege = privilege;
        }
    
        @Override
        public void run() {
            lock.lock();
            try {
    
                while (count <= 75) {
                    System.out.println(Thread.currentThread().getName() + " count: "+ count);
                    if (count % THREADNUM != privilege) {
                        condition.await();
                    } else {
                        System.out.println("Thread " + Thread.currentThread().getName() + " print :" + count++)
                        condition.signal();
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public static void main(String[] args) {
            new Thread(new ConditionTest(0)).start();
            new Thread(new ConditionTest(1)).start();
            new Thread(new ConditionTest(2)).start();
        }
    }

    跑了一下,能够正常运行,输出结果:

    Thread Thread-0 print :0

    Thread Thread-1 print :1

    Thread Thread-2 print :2

    ……

    但是多运行几次就出现问题了:出现一个很奇怪的现象,整个进程会卡死,什么!!卡死~

    问题就出在 condition.wait();看下面一个运行日志:

    Thread-2 count: 0
    Thread-1 count: 0
    Thread-0 count: 0
    Thread Thread-0 print :0
    Thread-0 count: 1
    Thread-2 count: 1

    3个线程运行的流程大致如下:

    线程2进入 -> 线程2wait –> 线程1进入 –> 线程1等待 –> 线程0进入

    -> 线程0运行print –> 线程0 signal() ->唤醒线程2-> 线程2 wait ->线程0wait 这个时候3个线程都处于wait状态。

    问题原因:signal()只会从等待队列里唤醒一个线程,如果这个线程不能继续signal就会出现问题。

    解决的办法:

    • condition.wait() 改为condition.waitNanos(200); 提供线程等待一定时间退出;
    • condition.signal()改为condition.signalAll();唤醒所有线程
  • 相关阅读:
    SpringBoot Jpa 双数据源mysql + oracle + liquibase+参考源码
    C#:将字符串中连续空格作为分隔符获取多段模糊查询的字符串
    C# 传入参数2021-05-18T00:00:00.000Z使用ToDateTime日期在此基础上加8小时
    修改DbContext并不是线程安全的bug处理。
    产品经理推荐书籍
    抽象类、类和接口
    git 分支合并主干出现冲突的解决办法
    HttpClient请求设置Content-Type标头空格问题
    C# 3Des加密解密
    WPF 颜色选择器
  • 原文地址:https://www.cnblogs.com/felixpan/p/8478246.html
Copyright © 2011-2022 走看看