文档章节

java并发控制:ReentrantLock Condition使用详解

张升强
 张升强
发布于 2015/06/16 14:11
字数 553
阅读 3096
收藏 16

我们通过一个实际的例子来解释Condition的用法:

我们要打印1到9这9个数字,由A线程先打印1,2,3,然后由B线程打印4,5,6,然后再由A线程打印7,8,9. 这道题有很多种解法,现在我们使用Condition来做这道题(使用Object的wait,notify方法的解法在这里)。

package cn.xband.locks;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test{
	static class NumberWrapper {
		public int value = 1;
	}

	public static void main(String[] args) {
		//初始化可重入锁
		final Lock lock = new ReentrantLock();
		
		//第一个条件当屏幕上输出到3
		final Condition reachThreeCondition = lock.newCondition();
		//第二个条件当屏幕上输出到6
		final Condition reachSixCondition = lock.newCondition();
		
		//NumberWrapper只是为了封装一个数字,一边可以将数字对象共享,并可以设置为final
		//注意这里不要用Integer, Integer 是不可变对象
		final NumberWrapper num = new NumberWrapper();
		//初始化A线程
		Thread threadA = new Thread(new Runnable() {
			@Override
			public void run() {
				//需要先获得锁
				lock.lock();
				try {
					System.out.println("threadA start write");
					//A线程先输出前3个数
					while (num.value <= 3) {
						System.out.println(num.value);
						num.value++;
					}
					//输出到3时要signal,告诉B线程可以开始了
					reachThreeCondition.signal();
				} finally {
					lock.unlock();
				}
				lock.lock();
				try {
					//等待输出6的条件
					reachSixCondition.await();
					System.out.println("threadA start write");
					//输出剩余数字
					while (num.value <= 9) {
						System.out.println(num.value);
						num.value++;
					}

				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {
					lock.unlock();
				}
			}

		});


		Thread threadB = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					lock.lock();
					
					while (num.value <= 3) {
						//等待3输出完毕的信号
						reachThreeCondition.await();
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {
					lock.unlock();
				}
				try {
					lock.lock();
					//已经收到信号,开始输出4,5,6
					System.out.println("threadB start write");
					while (num.value <= 6) {
						System.out.println(num.value);
						num.value++;
					}
					//4,5,6输出完毕,告诉A线程6输出完了
					reachSixCondition.signal();
				} finally {
					lock.unlock();
				}
			}

		});


		//启动两个线程
		threadB.start();
		threadA.start();
	}
}



上述代码中有完整的注释,请参考注释,理解Condition的用法。

基本思路就是首先要A线程先写1,2,3,这时候B线程应该等待reachThredCondition信号,而当A线程写完3之后就通过signal告诉B线程“我写到3了,该你了”,这时候A线程要等嗲reachSixCondition信号,同时B线程得到通知,开始写4,5,6,写完4,5,6之后B线程通知A线程reachSixCondition条件成立了,这时候A线程就开始写剩下的7,8,9了。

© 著作权归作者所有

共有 人打赏支持
张升强
粉丝 38
博文 119
码字总数 154023
作品 0
广州
高级程序员
加载中

评论(1)

xingkong513
xingkong513
这个例子是有bug
假如定义线程A的第一个lock为AL1,第二个为AL2,
线程B的也一样,BL1、BL2

执行顺序AL1、BL1一定先于AL2、BL2,
AL1、BL1哪个先都无所谓,因为在BL1中await是有num.value <= 3的判断,
但是AL2、BL2的执行顺序在例子中就必须为AL2先于BL2获取lock,否则线程会一直卡住,
如果要正常跑完,BL2需要判断num.value == 4时await(等于7时不wait)
【Java并发专题】27篇文章详细总结Java并发基础知识

努力的意义,就是,在以后的日子里,放眼望去全是自己喜欢的人和事! github:https://github.com/CL0610/Java-concurrency,欢迎题issue和Pull request。所有的文档都是自己亲自码的,如果觉...

你听___
05/06
0
0
Java多线程三(线程安全的集合及java.util.concurrent包的锁)

一、线程安全的集合 JDK1.5之前,可以使用Venctor和Hashtable,也可以由java.util.Collections来创建线程安全的集合,如:Connections.synchronizedSet(Set<T>); Connections.synchronizedLi......

dkz
2013/03/24
0
0
Java synchronized 和 ReentrantLock对比

Java synchronized 和 ReentrantLock对比 前段时间学习了java的线程同步的一些知识,认识到了线程同步的关键字synchronized 和 线程锁java.util.concurrent.lock包下的 ReentrantLock ,下面...

介鬼
06/16
0
0
JUC锁框架——重入锁ReentrantLock

重入锁(ReentrantLock)   ReentrantLock是一种可重入的互斥锁,并且加锁是一种显式操作,对逻辑控制的灵活性远远大于synchronized关键字。重入锁是可以完全替代synchronized。并且重入锁...

长头发-dawn
09/05
0
0
Java并发学习之ReentrantLock的工作原理及使用姿势

Lock,ReentrantLock的工作原理及使用方式 jdk提供实现线程同步,但有些场景下并不灵活,如多个同步方法,每次只能有一个线程访问;而Lock则可以非常灵活的在代码中实现同步机制 I. Lock的使用...

小灰灰Blog
2017/10/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

这周撸了两款小程序,分享下关键点。

本周撸了两款小程序,在这里总结下开发过程中的小经验,希望对大家有用。 小程序端 我们先说小程序要注意的地方。 ##默认入口转发问题 当一个小程序Page的js文件中存在 onShareAppMessage 方...

阿北2017
19分钟前
1
0
物联网技术很新吗?不!都是旧技术

通常,当我们想到物联网时,我们会想到新的、令人兴奋的现代技术。毕竟,还有什么比不用起床就能通过智能手机告诉咖啡机开始煮晨杯的“未来”更重要呢? 多亏了物联网,我们可以在世界任何地方...

linuxCool
26分钟前
1
0
利用责任链模式设计一个拦截器

前言 近期在做 Cicada 的拦截器功能,正好用到了责任链模式。 这个设计模式在日常使用中频率还是挺高的,借此机会来分析分析。 责任链模式 先来看看什么是责任链模式。 引用一段维基百科对其...

crossoverJie
45分钟前
2
0
属性动画

透明度 alpha 平移translationX/translationY 旋转 rotation 缩放 scaleX/scaleY 多个动画一起AnimatorSet 透明度 ObjectAnimator oa = ObjectAnimator.ofFloat(iv,"alpha" ......

lanyu96
45分钟前
1
0
Docker和Kubernetes如何让DevOps更具效力

缩短time-to-makrt对于任何一家企业都至关重要,这直接决定了客户满意度、市场竞争力乃至盈利能力。但在部署应用时,大多数企业内的IT团队都或多或少会遇到Dev和Ops之间的问题,这两个部门围...

好雨云帮
54分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部