前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java多线程编程-(6)-你还在使用wait/notify实现进程间的通信吗?

Java多线程编程-(6)-你还在使用wait/notify实现进程间的通信吗?

作者头像
Java后端技术
发布2018-08-09 14:50:46
6030
发布2018-08-09 14:50:46
举报
文章被收录于专栏:Java后端技术栈Java后端技术栈

在《Java多线程编程-(5)-线程间通信机制的介绍与使用》已经学习了,可以使用方法wait/notify 结合同步关键字synchronized实现同步和线程间通信,下边介绍一种更为方便的方式实现同步和线程间通信的效果,那就是Lock对象。

Lock对象简介

这里为什么说Lock对象哪?Lock其实是一个接口,在JDK1.5以后开始提供,其实现类常用的有ReentrantLock,这里所说的Lock对象即是只Lock接口的实现类,为了方便记忆或理解,都简称为Lock对象。

我们知道synchronized关键字可以实现线程间的同步互斥,从JDK1.5开始新增的ReentrantLock类能够达到同样的效果,并且在此基础上还扩展了很多实用的功能,比使用synchronized更佳的灵活。

下边,就开始一起学习一下ReentrantLock对象。

ReentrantLock实现线程同步

运行结果:

可以看出,当前线程打印完毕之后释放锁,其他线程才可以获取锁然后进行打印。线程打印的数据是分组打印的,这是因为当前线程已经持有锁,在当前线程打印完之后才会释放锁,但线程之间打印的顺序是随机的。

为了进一步说明使用ReentrantLock可以实现线程之间同步,测试代码如下:

运行结果:

可以看出,在sleep指定的时间内,当调用了lock.lock()方法线程就持有了”对象监视器”,其他线程只能等待锁被释放后再次争抢,效果和使用synchronized关键字是一样的。

使用Lock对象实现线程间通信

上述,已经大致看了一下如何使用ReentrantLock实现线程之间的同步,下边再看一下ReentrantLock是如何实现线程间通信的。

在前文中我们已经知道可以使用关键字synchronized与wait()方法和notify()方式结合实现线程间通信,也就是等待/通知模式。在ReentrantLock中,是借助Condition对象进行实现的。

Condition的创建方式如下:

Condition按字面意思理解就是条件,当然,我们也可以将其认为是条件进行使用,这样的话我们可以通过上述的代码创建多个Condition条件,我们就可以根据不同的条件来控制现成的等待和通知。而我们还知道,在使用关键字synchronized与wait()方法和notify()方式结合实现线程间通信的时候,notify/notifyAll的通知等待的线程时是随机的,显然使用Condition相对灵活很多,可以实现”选择性通知”。

这是因为,synchronized关键字相当于整个Lock对象只有一个单一的Condition对象,所有的线程都注册到这个对象上。线程开始notifAll的时候,需要通知所有等待的线程,让他们开始竞争获得锁对象,没有选择权,这种方式相对于Condition条件的方式在效率上肯定Condition较高一些。

下边,我们首先看一个实例。

使用Lock对象和Condition实现等待/通知实例

主要方法对比如下:

(1)Object的wait()方法相当于Condition类中的await()方法; (2)Object的notify()方法相当于Condition类中的signal()方法; (3)Object的notifyAll()方法相当于Condition类中的signalAll()方法;

首先,使用Lock的时候,和《Java多线程编程-(4)-线程间通信机制的介绍与使用》介绍的一样,都需要先获取锁。

示例代码如下:

运行结果:

可以看出结果正确执行!

使用Lock对象和多个Condition实现等待/通知实例

示例代码如下:

运行结果:

可以看出实现了分别通知。因此,我们可以使用Condition进行分组,可以单独的通知某一个分组,另外还可以使用signalAll()方法实现通知某一个分组的所有等待的线程。

公平锁和非公平锁

概念很好理解,公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配,即先进先出,那么他就是公平的;非公平是一种抢占机制,是随机获得锁,并不是先来的一定能先得到锁,结果就是不公平的。

ReentrantLock提供了一个构造方法,可以很简单的实现公平锁或非公平锁,源代码构造函数如下:

参数:fair为true表示是公平锁,反之为非公平锁,这里不再写代码测试。

ReentrantLock的其他方法

ReentrantLock源代码结构如下:

方法很简单,看到名称就可以想到作用是什么,挑一些简单介绍一下:

(1)getHoldCount()方法:查询当前线程保持此锁定的个数,也就是调用lock()的次数;

(2)getQueueLength()方法:返回正等待获取此锁定的线程估计数目;

(3)isFair()方法:判断是不是公平锁;

其他的不在介绍。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java后端技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档