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();
//主线程唤醒等待线程
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 = ;
while (!isOnSyncQueue(node)) {
LockSupport.park(this); // 3
if ((interruptMode = checkInterruptWhileWaiting(node)) != )
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != )
reportInterruptAfterWait(interruptMode);
}
主要分为3步:
- 把当前线程封装为一个Node节点,把节点加入等待队列
- fullyRelease()方法,释放锁
- 用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, )) // 2
return false;
Node p = enq(node);
int ws = p.waitStatus;
if (ws > || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread); // 3
return true;
}
- 从这段代码可以看到,signal()是唤醒等待队列中的第一个线程
- CAS更新节点状态
- 唤醒此节点代表的线程
如果要唤醒全部线程,可以调用signalAll()方法。如果想唤醒部分线程,可以实例化多个Condition配合使用。
ReentrantLock等待通知机制Condition介绍的更多相关文章
- 显式锁(四)Lock的等待通知机制Condition
任意一个Java对象,都拥有一组监视器方法(定义在根类Object上),主要包括:wait( ).wait(long timeout).notify().notifyAll()方法:这些方法与关 ...
- 12.详解Condition的await和signal等待通知机制
1.Condition简介 任何一个java对象都天然继承于Object类,在线程间实现通信的往往会应用到Object的几个方法,比如wait(),wait(long timeout),wait(lo ...
- 详解Condition的await和signal等待/通知机制
本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...
- Java并发编程,Condition的await和signal等待通知机制
Condition简介 Object类是Java中所有类的父类, 在线程间实现通信的往往会应用到Object的几个方法: wait(),wait(long timeout),wait(long tim ...
- Java并发之等待/通知机制
目录 1 前言 1.1 先来段代码放松一下 2 Object wait()/notify() 2.1 一段入门代码 2.2 问题三连击 a.为什么官方说wait() 要放在while里面? b.为什么 ...
- 超强图文|并发编程【等待/通知机制】就是这个feel~
你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough ...
- java多线程系列(三)---等待通知机制
等待通知机制 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理解 ...
- 【Java并发基础】使用“等待—通知”机制优化死锁中占用且等待解决方案
前言 在前篇介绍死锁的文章中,我们破坏等待占用且等待条件时,用了一个死循环来获取两个账本对象. // 一次性申请转出账户和转入账户,直到成功 while(!actr.apply(this, targe ...
- Java并发读书笔记:线程通信之等待通知机制
目录 synchronized 与 volatile 等待/通知机制 等待 通知 面试常问的几个问题 sleep方法和wait方法的区别 关于放弃对象监视器 在并发编程中,保证线程同步,从而实现线程之 ...
随机推荐
- 简记特定容器list和forward_list算法
链表类型list和forward_list有独有的sort.merge.remove.reverse和unique,而通用版本的是不能用于这两个类型的,因为所要求的迭代器不同,通用版本需要迭代器支持更 ...
- vim 复制
要复制到别的地方,用 "+y 来复制,注意是三个字符.gg"+yG 1.复制 1)单行复制 在命令模式下,将光标移动到将要复制的行处,按“yy”进行复制: 2)多行复制 在命令模式 ...
- Apache编译教程
手工编译安装Apache, 版本httpd-2.4.29(免费提供安装包,懒人福利:提供安装脚本):https://blog.51cto.com/13728740/2158576 编译安装apache ...
- activeMQ安全机制
- C++ STL bitset总结
基础用法 C++ Reference 神犇博客 余下的就是例题了 [BZOJ3687]简单题 考虑\(DP\),设\(f[i][j]\)表示前\(i\)个元素的算数和为\(j\)的子集个数,有: \[ ...
- 使用JLDAP操作LDAP,包含匿名连接、ldif导入导出、获取根节点、对数据的操作、LDAP错误码解析等
bean类 package com.cn.ccc.ggg.ldap.model; import javax.persistence.Entity; import javax.persistence.T ...
- 搜狗词库转txt
#环境需求 Python2 1 #!/bin/python # -*- coding: utf- -*- import struct import sys import binascii import ...
- qbzt day4 下午
有向图的强连通分量 强联通:两个点之间可以互相到达 如果某个图任意两个点都是强联通的,那么称这个图强联通 如果一个图的子图是强联通的,那么称这个图是强联通子图 一个图的极大强联通子图被称作强连通分量 ...
- hive_action
w pdf469 [不直接MR访问数据的工具 查询间接转化为MR] https://en.wikipedia.org/wiki/Apache_Hive Apache Hive supports a ...
- GMM demo
# GMM model # // library(mvtnorm) ) n1 = n2 = mu1 = c(,) mu2 = c(-,-) sigma1 = matrix(c(,.,.,),nrow= ...