java多线程系类:JUC锁:01之框架
本章,我们介绍锁的架构;后面的章节将会对它们逐个进行分析介绍。目录如下:
01. Java多线程系列--“JUC锁”01之 框架
02. Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock
03. Java多线程系列--“JUC锁”03之 公平锁(一)
04. Java多线程系列--“JUC锁”04之 公平锁(二)
05. Java多线程系列--“JUC锁”05之 非公平锁
06. Java多线程系列--“JUC锁”06之 Condition条件
07. Java多线程系列--“JUC锁”07之 LockSupport
08. Java多线程系列--“JUC锁”08之 共享锁和ReentrantReadWriteLock
09. Java多线程系列--“JUC锁”09之 CountDownLatch原理和示例
10. Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例
11. Java多线程系列--“JUC锁”11之 Semaphore信号量的原理和示例
根据锁的添加到Java中的时间,Java中的锁,可以分为"同步锁"和"JUC包中的锁"。
同步锁
即通过synchronized关键字来进行同步,实现对竞争资源的互斥访问的锁。Java 1.0版本中就已经支持同步锁了。
同步锁的原理是,对于每一个对象,有且仅有一个同步锁;不同的线程能共同访问该同步锁。但是,在同一个时间点,该同步锁能且只能被一个线程获取到。这样,获取到同步锁的线程就能进行CPU调度,从而在CPU上执行;而没有获取到同步锁的线程,必须进行等待,直到获取到同步锁之后才能继续运行。这就是,多线程通过同步锁进行同步的原理!
关于"同步锁"的更多内容,请参考"Java锁的基础部分"的内容。
JUC包中的锁
相比同步锁,JUC包中的锁的功能更加强大,它为锁提供了一个框架,该框架允许更灵活地使用锁,只是它的用法更难罢了。
JUC包中的锁,包括:Lock接口,ReadWriteLock接口,LockSupport阻塞原语,Condition条件,AbstractOwnableSynchronizer/AbstractQueuedSynchronizer/AbstractQueuedLongSynchronizer三个抽象类,ReentrantLock独占锁,ReentrantReadWriteLock读写锁。由于CountDownLatch,CyclicBarrier和Semaphore也是通过AQS来实现的;因此,我也将它们归纳到锁的框架中进行介绍。
先看看锁的框架图,如下所示。
01. Lock接口
JUC包中的 Lock 接口支持那些语义不同(重入、公平等)的锁规则。所谓语义不同,是指锁可是有"公平机制的锁"、"非公平机制的锁"、"可重入的锁"等等。"公平机制"是指"不同线程获取锁的机制是公平的",而"非公平机制"则是指"不同线程获取锁的机制是非公平的","可重入的锁"是指同一个锁能够被一个线程多次获取。
02. ReadWriteLock
ReadWriteLock 接口以和Lock类似的方式定义了一些读取者可以共享而写入者独占的锁。JUC包只有一个类实现了该接口,即 ReentrantReadWriteLock,因为它适用于大部分的标准用法上下文。但程序员可以创建自己的、适用于非标准要求的实现。
03. AbstractOwnableSynchronizer/AbstractQueuedSynchronizer/AbstractQueuedLongSynchronizer
AbstractQueuedSynchronizer就是被称之为AQS的类,它是一个非常有用的超类,可用来定义锁以及依赖于排队阻塞线程的其他同步器;ReentrantLock,ReentrantReadWriteLock,CountDownLatch,CyclicBarrier和Semaphore等这些类都是基于AQS类实现的。AbstractQueuedLongSynchronizer 类提供相同的功能但扩展了对同步状态的 64 位的支持。两者都扩展了类 AbstractOwnableSynchronizer(一个帮助记录当前保持独占同步的线程的简单类)。
04. LockSupport
LockSupport提供“创建锁”和“其他同步类的基本线程阻塞原语”。
LockSupport的功能和"Thread中的Thread.suspend()和Thread.resume()有点类似",LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程。但是park()和unpark()不会遇到“Thread.suspend 和 Thread.resume所可能引发的死锁”问题。
05. Condition
Condition需要和Lock联合使用,它的作用是代替Object监视器方法,可以通过await(),signal()来休眠/唤醒线程。
Condition 接口描述了可能会与锁有关联的条件变量。这些变量在用法上与使用 Object.wait 访问的隐式监视器类似,但提供了更强大的功能。需要特别指出的是,单个 Lock 可能与多个 Condition 对象关联。为了避免兼容性问题,Condition 方法的名称与对应的 Object 版本中的不同。
06. ReentrantLock
ReentrantLock是独占锁。所谓独占锁,是指只能被独自占领,即同一个时间点只能被一个线程锁获取到的锁。ReentrantLock锁包括"公平的ReentrantLock"和"非公平的ReentrantLock"。"公平的ReentrantLock"是指"不同线程获取锁的机制是公平的",而"非公平的 ReentrantLock"则是指"不同线程获取锁的机制是非公平的",ReentrantLock是"可重入的锁"。
ReentrantLock的UML类图如下:
(01) ReentrantLock实现了Lock接口。
(02) ReentrantLock中有一个成员变量sync,sync是Sync类型;Sync是一个抽象类,而且它继承于AQS。
(03) ReentrantLock中有"公平锁类"FairSync和"非公平锁类"NonfairSync,它们都是Sync的子类。ReentrantReadWriteLock中sync对象,是FairSync与NonfairSync中的一种,这也意味着ReentrantLock是"公平锁"或"非公平锁"中的一种,ReentrantLock默认是非公平锁。
07. ReentrantReadWriteLock
ReentrantReadWriteLock是读写锁接口ReadWriteLock的实现类,它包括子类ReadLock和WriteLock。ReentrantLock是共享锁,而WriteLock是独占锁。
ReentrantReadWriteLock的UML类图如下:
(01) ReentrantReadWriteLock实现了ReadWriteLock接口。
(02) ReentrantReadWriteLock中包含sync对象,读锁readerLock和写锁writerLock。读锁ReadLock和写锁WriteLock都实现了Lock接口。
(03) 和"ReentrantLock"一样,sync是Sync类型;而且,Sync也是一个继承于AQS的抽象类。Sync也包括"公平锁"FairSync和"非公平锁"NonfairSync。
08. CountDownLatch
CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
CountDownLatch的UML类图如下:
CountDownLatch包含了sync对象,sync是Sync类型。CountDownLatch的Sync是实例类,它继承于AQS。
09. CyclicBarrier
CyclicBarrier是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
CyclicBarrier的UML类图如下:
CyclicBarrier是包含了"ReentrantLock对象lock"和"Condition对象trip",它是通过独占锁实现的。
CyclicBarrier和CountDownLatch的区别是:
(01) CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则是允许N个线程相互等待。
(02) CountDownLatch的计数器无法被重置;CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的barrier。
10. Semaphore
Semaphore是一个计数信号量,它的本质是一个"共享锁"。
信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。
Semaphore的UML类图如下:
和"ReentrantLock"一样,Semaphore包含了sync对象,sync是Sync类型;而且,Sync也是一个继承于AQS的抽象类。Sync也包括"公平信号量"FairSync和"非公平信号量"NonfairSync。
-
Chandler Qian
Posted @ 2014-06-13 22:00写的真好! -
leoric xu
Posted @ 2014-08-05 17:0006点的(03)点有笔误吧怎么说ReentrantReadWriteLock去了? -
leoric xu
Posted @ 2014-08-05 17:0307里面也有笔误ReentrantLock是共享锁 -
iq527
Posted @ 2014-10-28 21:44@ leoric xu
应该是笔误吧. 这里应该是说ReadLock -
Ideasex
Posted @ 2016-06-18 14:06这文章都是你一个人写的? 若是,那lz真是太牛b了
java多线程系类:JUC锁:01之框架的更多相关文章
- Java多线程系列--“JUC锁”01之 框架
本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--“JUC锁”01之 框架02. Java多线程系列--“JUC锁”02之 互斥锁Reentrant ...
- Java多线程专题5: JUC, 锁
合集目录 Java多线程专题5: JUC, 锁 什么是可重入锁.公平锁.非公平锁.独占锁.共享锁 可重入锁 ReentrantLock A ReentrantLock is owned by the ...
- java多线程系类:JUC线程池:01之线程池架构
概要 前面分别介绍了"Java多线程基础"."JUC原子类"和"JUC锁".本章介绍JUC的最后一部分的内容--线程池.内容包括:线程池架构 ...
- java多线程系类:基础篇:01基本概念:
这个系类的内容全部来源于http://www.cnblogs.com/skywang12345/p/3479024.html.特别在此声明!!! 本来想直接看那位作家的博客的,但还是复制过来. 多线程 ...
- java多线程系类:JUC线程池:02之线程池原理(一)
在上一章"Java多线程系列--"JUC线程池"01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我 ...
- java多线程系类:JUC线程池:03之线程池原理(二)(转)
概要 在前面一章"Java多线程系列--"JUC线程池"02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包 ...
- java多线程系类:JUC线程池:04之线程池原理(三)(转)
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--"基础篇& ...
- java多线程系类:JUC原子类:03之AtomicLongArray原子类
概要 AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray这3个数组类型的原子类的原理和用法相似.本章以AtomicLongArray对数 ...
- java多线程系类:基础篇:06线程让步
本系类的知识点全部来源于http://www.cnblogs.com/skywang12345/p/3479243.html,我只是复制粘贴一下,特在此说明. 概要 本章,会对Thread中的线程让步 ...
随机推荐
- error C2664: 'BOOL (PCERT_SELECT_STRUCT_A)' : cannot convert parameter 1 from 'CERT_SELECT_STRUCT *' to 'PCERT_SELECT_STRUCT_A'
1. 编译c++程序出现标题所示错误 2. 解决方法:更改编码设置
- Apache Lucene(全文检索引擎)—搜索
目录 返回目录:http://www.cnblogs.com/hanyinglong/p/5464604.html 本项目Demo已上传GitHub,欢迎大家fork下载学习:https://gith ...
- css中vertical-align垂直居中的认识
目标大纲 1.vertical-align为何不起作用?? vertical-align只钟情于“inline-block内联块级元素/inline元素” vertical-align属性 text- ...
- jQuery带tab切换搜索框样式代码
效果体验:http://hovertree.com/texiao/jquery/23/ 代码如下,保存到HTML文件也可以查看效果: <!DOCTYPE html> <html la ...
- ["1", "2", "3"].map(parseInt)?
["1", "2", "3"].map(parseInt)得到什么? 答案是:[1, NaN, NaN]. 原因:parseInt接收的是两 ...
- tomcat远程调试javaweb
当把一个本地项目部署到远程服务器后有可能出现意想不到错误,这个时候通过远程调试能够更清楚的找到bug所在位置. 目前百度tomcat绝大多数方法都是在startup.sh或者catalina.sh增加 ...
- Aspose.Words基本操作
一个非常好用的控件. 基本的操作可以参考伍大神的文章: http://www.cnblogs.com/wuhuacong/archive/2012/08/30/2662961.html 在这里补充四点 ...
- iOS 二维码扫描
// 导入 AVFoundation.framwork 框架#import "HDCodeViewController.h" #import "HDNormalViewC ...
- 如何将github上的 lib fork之后通过podfile 改变更新源到自己fork的地址
解决办法: http://stackoverflow.com/questions/20936885/cocoapods-and-github-forks 就是fork完后,提交更改到自己的github ...
- asp.net mvc 之旅—— 第三站 路由模板中强大的自定义IRouteConstraint约束
我们在写mvc的时候,经常会配置各种url模板,比如controller,action,id 组合模式,其实呢,我们还可以对这三个参数进行单独的配置,采用的方式自然 就是MapRoute中的const ...