ReentrantLock等待通知机制Condition介绍

  Object类中的wait(),notify()和notifyAll()可以实现线程的等待通知模型,同样在ReentrantLock中可以借助Condition来完成这种机制。本篇就简要介绍Condition的工作原理。

  先看一下Condition的使用示例:

public class LockConditionTest {
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    /**
     * 等待方法
     */
    private void startAwait() {
        try {
            lock.lock();
            System.out.println("开始等待:" + System.currentTimeMillis());
            condition.await();
            System.out.println("等待结束:" + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            lock.unlock();
        }
    }

    /**
     * 释放方法
     */
    private void startSignal() {
        try {
            lock.lock();
            System.out.println("开始释放");
            condition.signal();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //这里锁被主线程持有,必须释放,让被唤醒的MyThread能够得到锁
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        LockConditionTest test = new LockConditionTest();
        MyThread myThread = new LockConditionTest().new MyThread(test);
        //开始线程。 让线程等待。
        myThread.start();
        //myThread调用condition.await()释放锁,main线程开始执行
        TimeUnit.MILLISECONDS.sleep(1000);
        //主线程唤醒等待线程
        test.startSignal();
    }

    class MyThread extends Thread{
        private LockConditionTest test;

        public MyThread(LockConditionTest test) {
            this.test = test;
        }

        @Override
        public void run() {
            //开始等待,释放锁
            test.startAwait();
        }
    }

}

  这段代码的输出为:

开始等待:1550285191899
开始释放
等待结束:1550285192902

  等待时间大概为1000毫秒,符合预期。

  

下面看看Condition的await()方法:

public final void await() throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();    // 1
            int savedState = fullyRelease(node);  // 2
            int interruptMode = 0;
            while (!isOnSyncQueue(node)) {
                LockSupport.park(this);   // 3
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null) // clean up if cancelled
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
        }

  主要分为3步:

  1. 把当前线程封装为一个Node节点,把节点加入等待队列
  2. fullyRelease()方法,释放锁
  3. 用LockSupport.park()挂起当前线程

再看看signal()方法:

public final void signal() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            Node first = firstWaiter;    // 1
            if (first != null)
                doSignal(first);
        }

private void doSignal(Node first) {
            do {
                if ( (firstWaiter = first.nextWaiter) == null)
                    lastWaiter = null;
                first.nextWaiter = null;
            } while (!transferForSignal(first) &&
                     (first = firstWaiter) != null);
        }

final boolean transferForSignal(Node node) {
        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))    // 2
            return false;

        Node p = enq(node);
        int ws = p.waitStatus;
        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
            LockSupport.unpark(node.thread);           // 3
        return true;
    }
  1. 从这段代码可以看到,signal()是唤醒等待队列中的第一个线程
  2. CAS更新节点状态
  3. 唤醒此节点代表的线程

  如果要唤醒全部线程,可以调用signalAll()方法。如果想唤醒部分线程,可以实例化多个Condition配合使用。

原文地址:https://www.cnblogs.com/sunshine-ground-poems/p/10387181.html

时间: 2024-11-05 12:31:15

ReentrantLock等待通知机制Condition介绍的相关文章

显式锁(四)Lock的等待通知机制Condition

?? 任意一个Java对象,都拥有一组监视器方法(定义在根类Object上),主要包括:wait( ).wait(long timeout).notify().notifyAll()方法:这些方法与关键字synchronized结合使用,可以实现 隐式锁的等待/通知机制.而显示锁Lock也实现了等待/通知机制:Condition接口也提供了类似Object的监视器方法,与Lock配合使用可以实现 显式锁的等待/通知机制,但是两者在使用方式和功能特性有所差别.总得来说,Condition接口更加灵

12.详解Condition的await和signal等待通知机制

1.Condition简介 任何一个java对象都天然继承于Object类,在线程间实现通信的往往会应用到Object的几个方法,比如wait(),wait(long timeout),wait(long timeout, int nanos)与notify(),notifyAll()几个方法实现等待/通知机制,同样的, 在java Lock体系下依然会有同样的方法实现等待/通知机制.从整体上来看Object的wait和notify/notifyAll是与对象监视器配合完成线程间的等待/通知机制

Java并发之等待/通知机制

目录 1 前言 1.1 先来段代码放松一下 2 Object wait()/notify() 2.1 一段入门代码 2.2 问题三连击 a.为什么官方说wait() 要放在while里面? b.为什么wait()必须在同步方法/代码块中调用? c.为什么wait(), notify() 和 notifyAll()是定义在Object里面而不是在Thread里面? 2.3 wait(long timeout) 3 Condition await()/signal() 3.1 用Condition进

超强图文|并发编程【等待/通知机制】就是这个feel~

你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough 现陆续将Demo代码和技术文章整理在一起 Github实践精选 ,方便大家阅读查看,本文同样收录在此,觉得不错,还请Star 并发编程为什么会有等待通知机制 上一篇文章说明了 Java并发死锁解决思路 , 解决死锁的思路之一就是 破坏请求和保持条件, 所有柜员都要通过唯一的账本管理员一次性拿到所有

二 Java利用等待/通知机制实现一个线程池

接着上一篇博客的 一Java线程的等待/通知模型 ,没有看过的建议先看一下.下面我们用等待通知机制来实现一个线程池 线程的任务就以打印一行文本来模拟耗时的任务.主要代码如下: 1  定义一个任务的接口. 1 /* 2 * 任务的接口 3 */ 4 public interface Task { 5 void doSomething(); 6 } 2  实现一个具体的任务. 1 /* 2 * 具体的任务 3 */ 4 public class PrintTask implements Task{

内置锁(二)synchronized下的等待通知机制

一.等待/通知机制的简介 线程之间的协作: ??为了完成某个任务,线程之间需要进行协作,采取的方式:中断.互斥,以及互斥上面的线程的挂起.唤醒:如:生成者--消费者模式.或者某个动作完成,可以唤醒下一个线程.管道流已准备等等: 等待/通知机制: ? ?等待/通知机制 是线程之间的协作一种常用的方式之一,在显示锁Lock 和 内置锁synchronized都有对应的实现方式. 等待/通知机制 经典的使用方式,便是在生产者与消费者的模式中使用: 1.生产者负责生产商品,并送到仓库中存储: 2.消费者

Java多线程之三volatile与等待通知机制示例

原子性,可见性与有序性 在多线程中,线程同步的时候一般需要考虑原子性,可见性与有序性 原子性 原子性定义:一个操作或者多个操作在执行过程中要么全部执行完成,要么全部都不执行,不存在执行一部分的情况. 以我们在Java代码中经常用到的自增操作i++为例,i++实际上并不是一步操作,而是首先对i的值加一,然后将结果再赋值给i.在单线程中不会存在问题,但如果在多线程中我们考虑这样一个情况:i是一个共享变量,初始值为0,假设线程一以执行到某一步正好进行自增操作i++,刚好对i进行了加一但是还没将值重新赋

再谈AbstractQueuedSynchronizer:共享模式与基于Condition的等待/通知机制实现

共享模式acquire实现流程 上文我们讲解了AbstractQueuedSynchronizer独占模式的acquire实现流程,本文趁热打铁继续看一下AbstractQueuedSynchronizer共享模式acquire的实现流程.连续两篇文章的学习,也可以对比独占模式acquire和共享模式acquire的区别,加深对于AbstractQueuedSynchronizer的理解. 先看一下共享模式acquire的实现,方法为acquireShared和acquireSharedInte

《Java并发编程的艺术》读书笔记:等待/通知机制

看这本书之前,对wait和notify认识大概就是,调用wait的线程A堵塞之后,一旦另外有线程调用notify方法.线程A会立马从wait方法处返回.看完这本书后.发现自己的认识实在太肤浅了..... . 线程调用wait()后,会释放已经获得的锁. 同一时候进入Waiting状态,而非Blocked状态.唯独等待其它的线程调用notify()方法且释放锁之后.当前线程才会从wait()方法处返回.只发出通知是不够用的.还须要发出通知的线程释放锁. 然而notify()方法的调用并不意味着锁的