JUC锁简析(基于源码的详解后续会陆续发出)
Posted tianxin945
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JUC锁简析(基于源码的详解后续会陆续发出)相关的知识,希望对你有一定的参考价值。
张图说明下要分享的内容:
01. Lock接口
JUC包中的 Lock 接口支持那些语义不同(重入、公平等)的锁规则。所谓语义不同,是指锁可是有"公平机制的锁"、"非公平机制的锁"、"可重入的锁"等等。
"公平机制"是指"不同线程获取锁的机制是公平的", 而"非公平机制"则是指"不同线程获取锁的机制是非公平的","可重入的锁"是指同一个锁能够被一个线程多次获取。
02. ReentrantLock
ReentrantLock是独占锁。所谓独占锁,是指只能被独自占领,即同一个时间点只能被一个线程锁获取到的锁。
ReentrantLock锁包括"公平的ReentrantLock"和"非公平的ReentrantLock"。
"公平的ReentrantLock"是指"不同线程获取锁的机制是公平的",而"非公平的ReentrantLock"则是指"不同线程获取锁的机制是非公平的",
ReentrantLock是"可重入的锁"。
ReentrantLock中有一个成员变量sync,sync是Sync类型;Sync是一个抽象类,而且它继承于AQS。
ReentrantLock中有"公平锁类"FairSync和"非公平锁类"NonfairSync,它们都是Sync的子类。ReentrantReadWriteLock中sync对象,是FairSync与NonfairSync中的一种, 这也意味着ReentrantLock是"公平锁"或"非公平锁"中的一种,ReentrantLock默认是非公平锁。
03. CyclicBarrier
CyclicBarrier是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
CyclicBarrier是包含了"ReentrantLock对象lock"和"Condition对象trip",它是通过独占锁实现的。
CyclicBarrier和CountDownLatch的区别是: CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则是允许N个线程相互等待。
CountDownLatch的计数器无法被重置;CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的barrier。
04. ReadWriteLock
ReadWriteLock 接口以和Lock类似的方式定义了一些读取者可以共享而写入者独占的锁。
JUC包只有一个类实现了该接口,即 ReentrantReadWriteLock,因为它适用于大部分的标准用法上下文。 但
程序员可以创建自己的、适用于非标准要求的实现。
05. ReentrantReadWriteLock ReentrantReadWriteLock是读写锁接口ReadWriteLock的实现类,它包括子类ReadLock和WriteLock。ReadLock是共享锁,而WriteLock是独占锁。
ReentrantReadWriteLock实现了ReadWriteLock接口。 ReentrantReadWriteLock中包含sync对象,读锁readerLock和写锁writerLock。读锁ReadLock和写锁WriteLock都实现了Lock接口。
和"ReentrantLock"一样,sync是Sync类型;而且,Sync也是一个继承于AQS的抽象类。Sync也包括"公平锁"FairSync和"非公平锁"NonfairSync。
06. AbstractOwnableSynchronizer/AbstractQueuedSynchronizer/AbstractQueuedLongSynchronizer
AbstractQueuedSynchronizer就是被称之为AQS的类,它是一个非常有用的超类,可用来定义锁以及依赖于排队阻塞线程的其他同步器; ReentrantLock,ReentrantReadWriteLock,CountDownLatch,CyclicBarrier和Semaphore等这些类都是基于AQS类实现的。 AbstractQueuedLongSynchronizer 类提供相同的功能但扩展了对同步状态的 64 位的支持。两者都扩展了类 AbstractOwnableSynchronizer(一个帮助记录当前保持独占同步的线程的简单类)。
07. LockSupport
LockSupport提供“创建锁”和“其他同步类的基本线程阻塞原语”。 LockSupport的功能和"Thread中的Thread.suspend()和Thread.resume()有点类似",LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程。 但是park()和unpark()不会遇到“Thread.suspend 和 Thread.resume所可能引发的死锁”问题。
实现原理是通过二元信号量做的阻塞,要注意的是,这个信号量最多只能加到1。我们也可以理解成获取释放许可证的场景。 unpark()方法会释放一个许可证,park()方法则是获取许可证,如果当前没有许可证,则进入休眠状态,知道许可证被释放了才被唤醒。无论执行多少次unpark()方法,也最多只会有一个许可证。据说源码中通过其创建锁。
1) LockSupport不需要获取对象的监视器
2) lockSupport 调用 native的park ,unpark方法。
08. Condition
Condition需要和Lock联合使用,它的作用是
代替Object监视器方法,可以通过await(),signal()来休眠/唤醒线程。 Condition 接口描述了可能会与锁有关联的条件变量。这些变量在用法上与使用 Object.wait 访问的隐式监视器类似,但提供了更强大的功能。 需要特别指出的是,单个 Lock 可能与多个 Condition 对象关联。为了避免兼容性问题,Condition 方法的名称与对应的 Object 版本中的不同。
Object中wait(),notify(),notifyAll()方法是和"同步锁"(synchronized关键字)捆绑使用的;而Condition是需要与"互斥锁"/"共享锁"捆绑使用的。它更强大的地方在于:能够更加精细的控制多线程的休眠与唤醒。对于同一个锁,我们可以创建多个Condition,在不同的情况下使用不同的Condition。
09. CountDownLatch
CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
CountDownLatch包含了sync对象,sync是Sync类型。CountDownLatch的Sync是实例类,它继承于AQS。
10. Semaphore
Semaphore是一个计数信号量,它的本质是一个"共享锁"。 信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。Semaphore 是 synchronized 的加强版,作用是控制线程的并发数量。
和"ReentrantLock"一样,Semaphore包含了sync对象,sync是Sync类型;而且,Sync也是一个继承于AQS的抽象类。Sync也包括"公平信号量"FairSync和"非公平信号量"NonfairSync。
二、countDownLatch,CyclicBarrier,Semaphore区别简析
1、CountDownLatch线程运行到某个点后,计数值-1,该线程继续运行,直到计数值为0,则停止运行,
2、CyclicBarrier只能唤醒一个任务,但是可以重复使用,比如每个人有10块钱,每10个人来就可以凑齐100块,换一张毛爷爷哈哈哈哈。
3、Semaphore控制线程的并发数量,比如停车,这里只有3个车位,停满了就不能停了,必须等有车开走才能再放一辆车进来停。
以上是关于JUC锁简析(基于源码的详解后续会陆续发出)的主要内容,如果未能解决你的问题,请参考以下文章
ReentrantLock源码简析
JUC源码分析13-locks-ReentrantReadWriteLock
#yyds干货盘点# JUC锁: LockSupport详解
CMake 手册详解
#yyds干货盘点# JUC锁: ReentrantLock详解
AQS详解之独占锁模式