100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 常用并发工具类(锁和线程间通信工具类)

常用并发工具类(锁和线程间通信工具类)

时间:2021-04-04 14:13:31

相关推荐

常用并发工具类(锁和线程间通信工具类)

常用并发工具类总结

JUC下的常用并发工具类(锁和线程间通信工具类),主要包括ReentrantLockReentrantReadWriteLockCountDownLatchCyclicBarrierSemaphoreExchanger

ReentrantLock 和 ReentrantReadWriteLock

ReentrantLock是可重入独占锁,ReentrantReadWriteLock是可重入读写锁。

ReentrantLock

ReentrantLock支持公平和非公平锁两种模式,可以通过new ReentrantLock(boolean fair)构造方法来指定公平或非公平模式,默认为非公平模式。

注意,公平和非公平模式在这里主要指的是尝试获取锁的线程是否会在排到同步队列末尾之前尝试获取一遍锁

如果在排到队尾之前会尝试获取一边锁,那么就是非公平模式,因为有可能在这一次尝试获取就直接得到了锁,等同于一个插队操作,所以是非公平锁如果是老老实实排到队尾,那么就是公平模式,因为不会存在插队操作

ReentrantLock的公平与非公平模式,主要是靠其内部的两个AQS子类,FairSyncNonfairSync来实现的。

RenntrantReadWriteLock

ReentrantReadWriteLock是读写锁,其主要性质如下:

ReentrantReadWriteLock内部有一个Sync对象,用于执行所有的同步机制Sync类继承了AQSSync类有一个公平锁实现FairSync,和一个非公平锁实现NonfairSyncSync类中state的含义为,高16位代表获取读锁的次数,低16位代表获取写锁的次数 内部有一个ReadLock对象(读锁),有一个WriteLock对象(写锁) 读锁和写锁实际上都是依赖于Sync对象来实现的基于Sync对象对于state的定义,读锁和写锁的获取次数上限都为 65535 (2^16-1)读锁的加锁操作本质上是对state的高16位进行+1操作,释放锁本质上是对state的高16位进行-1操作写锁的加锁操作本质上是对state的低16位进行+1操作,释放锁本之上是对state的低16位进行-1操作 操作顺序与互斥关系 读读不互斥写写互斥读写互斥写读互斥 读锁和写锁均可重入读锁不能升级为写锁(即持有读锁时去获取写锁) 如果使用writeLock().lock()获取写锁会发生死锁如果使用writeLock().tryLock(long timeout, Timeunit unit)会在超时后返回 写锁可以降级为读锁(即持有写锁时去获取读锁)读锁和写锁的加锁和释放锁的逻辑必须成对出现

Semaphore

Semaphore信号量的意思,主要用于限定临界资源同时能被多少个线程访问。主要特性:

内部有一个Sync类继承了AQS,是AQS共享模式的一种具体实现Sync类有一个公平锁实现FairSync,和一个非公平锁实现NonfairSync,由构造函数public Semaphore(int permits, boolean fair)来指定 公平锁实现,当前线程获取不到许可时,将会进入队列等待非公平锁实现,当前线程将会一直(自旋)尝试获取许可Sync类中state的含义为public Semaphore(int permits)permits的数值(许可的数量Sync类的获取许可操作本质上是对state-1操作,释放许可操作本之上是对state+1操作

Exchanger

Exchanger交换器的意思,主要用于两个线程之间的数据交换。

注意在多个线程同时使用一个Exchanger对象进行数据交换的时候,交换结果可能是未知的。所以Exchanger适用于成对线程之间的数据通信。

CyclicBarrier

CyclicBarrier循环栅栏的意思,主要用于帮助多个线程同时达到某个等待点后再把这些线程唤醒。主要特性:

主要的构造函数为public CyclicBarrier(int parties)public CyclicBarrier(int parties, Runnable barrierAction)parties代表的是参与协作的线程数量barrierAction代表的是协作线程的数量等于parties时,将会执行的动作CyclicBarrier有一把内置的ReentrantLock锁,和由这把锁创建出来的一个Condition对象当调用await()方法时,首先会尝试获取锁,获取成功后当前需要等待的剩余协作线程数量-1如果此时需要等待的剩余协作线程数量不为0,即代表参与协作的线程数量还没有到达初始设定的数量,则调用Condition对象的await()方法,将当前线程阻塞在Condition对象的条件队列中如果此时需要等待的协作线程数量为0,即代表参与协作的线程数量已经到达了初始设定的数量,则执行打开栅栏动作(调用nextGeneration()方法),(调用Condition对象的singalAll()方法)唤醒所有等待在Condition对象上的线程,唤醒完成后,重置栅栏到初始状态 当调用reset()方法时,之前调用了await()方法的所有线程将会被唤醒,并抛出异常当某个线程调用了await()方法后被中断,那么CyclicBarrier会被设置成一个中断状态,此时需要调用reset()方法把CyclicBarrier对象重置成初始状态

总的来说 ,CyclicBarrier是通过AQS的条件等待机制(ConditionObject)来实现的

CountDownLatch

CountDownLatch计数门闩的意思,主要用于在一组执行线程都到达某个等待点之后,再唤醒等待在这个门闩上的所有线程一个同步工具。

内部有一个Sync类继承了AQS,是AQS共享模式的一种具体实现Sync类中state的含义为public CountDownLatch(int count)count的数值(需要打开门闩的次数)调用countDown()方法后(相当于尝试释放共享锁),将会使用CAS+ 自旋将state变量值-1调用await()方法后(相当于尝试获取共享锁),首先会判断当前的state是否等于0如果等于0,则获取成功,将会立马返回如果不等于0,则获取失败,当前线程将会被封装为共享节点放入到AQS同步队列中,并阻塞

CyclicBarrier 和 CountDownLatch 的异同

相同点:

都是JUC包下的同步工具类都是AQS的应用实例都可以在指定数目个线程到达某个等待点后,执行一些动作

不同点:

实现目标不同:CyclicBarrier是帮助多个协作线程最终都到达某个等待点后,再同时唤醒这些协作线程本身CountDownLatch是在多个执行线程最终都到达某个等待点后,再同时唤醒所有等待线程 调用方式不同:CyclicBarrier调用await()方法后,如果此时的count值不为0,那么将会阻塞自身,所以不能在同一时间连续调用CountDownLatch在调用countDown()方法后,不会阻塞自身,在同一时间可以连续调用 阻塞、修改计数计数和通知的对象不一样:CyclicBarrier阻塞、修改计数和通知的对象都是执行await()方法的线程CountDownLatch阻塞和通知的是调用await()方法的线程,修改计数的对象是执行countDown()方法的线程 实现方式不同:CyclicBarrier是基于AQS的条件等待机制来实现的CountDownLatch内部有一个Sync类直接继承了AQS,是AQS共享机制的一种实现 状态是否可重置:CyclicBarrier可以在到达计数条件后重置自身状态,可以重复使用;也可以主动调用reset()方法来重置自身状态CountDownLatch不能重置自身状态,不能重复使用 计数条件到达后是否可以执行操作:CyclicBarrier可以调用public CyclicBarrier(int parties, Runnable barrierAction)中传入计数条件到达后的操作。在计数条件到达之后,将会调用barrierActionrun()方法执行一些特殊操作CountDownLatch不能设置计数条件到达后的执行操作

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。