多线程学习笔记二之JUC组件
概述
为了对共享资源提供更细粒度的同步控制,JDK5新增了java.util.concurrent(JUC)并发工具包,并发包新增了Lock接口(以及相关实现类)用来实现锁功能,它提供了与synchronized关键字相似的同步功能,只是在使用时需要显式地获取和释放锁,还具备内置锁不具备的自由操作锁获取和释放、可中断地获取锁以及超时获取锁等多种synchronized关键字不具备的同步特性。
为了实现JUC提出的各种功能的锁,JUC包的作者,并发大师Doug Lee提出了同步器 synchronizer的概念,在同步器中定义了共享资源的同步状态,维护了一个双端的先入先出的同步队列用于存放获取共享资源失败而等待的线程,线程利用同步器实现的锁获取共享资源流程如下:

为了实现上述操作,需要下面三个基本组件的相互协作:
- 对共享资源同步状态进行原子性管理 ---> 利用CAS对同步状态进行更新
- 线程的阻塞与唤醒 ---> 调用native方法
- 等待队列的管理 ---> 维护FIFO队列
由此可以看出,同步器是实现锁的关键,同步器面向的是线程访问和资源控制,它定义了线程对资源是否能够获取以及线程的排队等操作。关于同步器的详细解释会在AQS(AbstractQueuedSynchronizer)解析里给出。
JUC锁框架图
JUC中Lock接口定义了锁的规范,各种功能的锁都实现了Lock接口,各个锁以内部类继承AQS同步器的方式聚合了同步器,从而以同步器为基石实现具体功能的锁。

Lock
Lock接口为独占锁(同一时间共享资源只能由一个线程获取),共享锁(同一时间共享资源可由多个线程获取),公平锁(各个线程获得锁的机会是公平的),非公平锁(各个线程获得锁的机会是公平的),重入锁(线程在获取到锁之后,再次获取该锁而不会被该锁所阻塞,不会自己把自己锁在外面)提供了实现规范,接口中定义的方法如下:

AbstractQueuedSynchronizer
AbstractQueuedSynchronizer就是被称之为AQS的类,可以用于构建锁或者其他相关同步装置的基础框架。从图中也可以看出,ReentrantLock,ReentrantReadWriteLock,CountDownLatch,CyclicBarrier和Semaphore这些类通过内部类继承AQS的方式来实现锁的功能。Condition
Condition需要和Lock联合使用,它的作用是代替Object监视器方法,可以通过await(),signal()来休眠/唤醒线程。Condition 接口描述了可能会与锁有关联的条件变量。这些变量在用法上与使用 Object.wait 访问的隐式监视器类似,但提供了更强大的功能,接口中定义的方法如下:

LockSurport
LockSupport中的park() 和 unpark()调用native方法将线程休眠。ReentrantLock
ReentrantLock对与共享资源采取的是较为保守的独占策略,即只有一个线程能够获得锁;ReentrantLock支持公平锁和非公平锁,默认是非公平锁;从名称也能看出,ReentrantLock是可重入锁。ReentrantReadWriteLock
ReentrantReadWriteLock是读写锁接口ReadWriteLock的实现类,它包括子类ReadLock和WriteLock。ReentrantLock是共享锁,而WriteLock是独占锁。CountDownLatch
CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。CyclicBarrier
CyclicBarrier是一个同步辅助类,允许一组线程互相等待,直到到达某个公共屏障点(common barrier point)。因为该barrier在释放等待线程后可以重用,所以称它为循环的barrier。Semaphore
Semaphore是一个计数信号量,它的本质是一个"共享锁"。信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。 线程可以通过release()来释放它所持有的信号量许可。
使用内置锁还是JUC显示锁?
JUC中的显示锁提供了与synchronized内置锁相同的互斥性与内存可见性,那么我们的多线程代码到底使用哪一种锁来实现同步呢?首先从性能角度考虑,在JDK5 显示锁刚推出时,性能是大幅领先于内置锁的,在随后的JDK版本中,JVM对内置锁进行了性能优化,现在二者的性能已经没有明显优劣之分;从功能使用上,内置锁的使用较为简单,无需手动获得以及释放锁,而显示锁的功能更为强大,具有更高的灵活性,当我们需要使用到锁的高级功能,如以响应中断/支持超时的方式获取锁或者自定义实现锁,这时候可以考虑内置锁。
多线程学习笔记二之JUC组件的更多相关文章
- 多线程学习笔记(二) BackgroundWorker 和 ProgressChanged
BackgroundWorker是在内部使用了线程池的技术:同时,在Winform 或WPF编码中,它还给工作线程和UI线程提供了交互的能力. Thread和ThreadPool默认都没有提供这种交互 ...
- java多线程学习笔记——详细
一.线程类 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...
- amazeui学习笔记二(进阶开发5)--Web 组件开发规范Rules
amazeui学习笔记二(进阶开发5)--Web 组件开发规范Rules 一.总结 1.见名知意:见那些class名字知意,见函数名知意,见文件名知意 例如(HISTORY.md Web 组件更新历史 ...
- amazeui学习笔记二(进阶开发2)--Web组件简介Web Component
amazeui学习笔记二(进阶开发2)--Web组件简介Web Component 一.总结 1.amaze ui:amaze ui是一个web 组件, 由模板(hbs).样式(LESS).交互(JS ...
- C#学习笔记——面向对象、面向组件以及类型基础
C#学习笔记——面向对象.面向组件以及类型基础 目录 一 面向对象与面向组件 二 基元类型与 new 操作 三 值类型与引用类型 四 类型转换 五 相等性与同一性 六 对象哈希码 一 面向对象与面向组 ...
- muduo学习笔记(二)Reactor关键结构
目录 muduo学习笔记(二)Reactor关键结构 Reactor简述 什么是Reactor Reactor模型的优缺点 poll简述 poll使用样例 muduo Reactor关键结构 Chan ...
- java之jvm学习笔记二(类装载器的体系结构)
java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次性解释代码,也就是当字节码转载到内存后,每次需要都会重新 ...
- JAVA多线程学习笔记(1)
JAVA多线程学习笔记(1) 由于笔者使用markdown格式书写,后续copy到blog可能存在格式不美观的问题,本文的.mk文件已经上传到个人的github,会进行同步更新.github传送门 一 ...
- java进阶-多线程学习笔记
多线程学习笔记 1.什么是线程 操作系统中 打开一个程序就是一个进程 一个进程可以创建多个线程 现在系统中 系统调度的最小单元是线程 2.多线程有什么用? 发挥多核CPU的优势 如果使用多线程 将计算 ...
随机推荐
- 在kubernetes集群中创建redis主从多实例
分类 > 正文 在kubernetes集群中创建redis主从多实例 redis-slave镜像制作 redis-master镜像制作 创建kube的配置文件yaml 继续使用上次实验环境 ht ...
- python 爬虫 scrapy1_官网教程
Python爬虫视频教程零基础小白到scrapy爬虫高手-轻松入门 https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.482434a6E ...
- 鸟哥的Linux私房菜——第十章
视频链接 土豆网:http://www.tudou.com/programs/view/YI5fpob0Wwk B站(推荐):http://www.bilibili.com/video/av98064 ...
- Dubbo学习笔记10:Dubbo服务消费方启动流程源码分析
同理我们看下服务消费端启动流程时序图: 在<Dubbo整体架构分析>一文中,我们提到服务消费方需要使用ReferenceConfig API来消费服务,具体是调用代码(1)get()方法来 ...
- gcc初步窥探
由于没有上过Linux编程这门课,所以Linux学得很水啊!!用来用去都是ls -al ; cd .. ;这些渣命令,尤其gcc都不知道什么东西来的,所以先学一下吧. 一.程序的编译过程 对于GUN编 ...
- 关于SQL注入,你应该知道的那些事
戴上你的黑帽,现在我们来学习一些关于SQL注入真正有趣的东西.请记住,你们都好好地用这些将要看到的东西,好吗? SQL注入攻击因如下几点而是一种特别有趣的冒险: 1.因为能自动规范输入的框架出现,写出 ...
- ASP.NET乱码深度剖析
写在前面 在Web开发中,乱码应该算一个常客了.今天还好好的一个页面,第二天过来打开一看,中文字符全变“外星文”了.有时为了解决这样的问题,需要花上很长的时间去调试,直至抓狂,笔者也曾经历过这样的时期 ...
- 20155232 2016-2017-3 《Java程序设计》第8周学习总结
20155232 2016-2017-3 <Java程序设计>第8周学习总结 教材学习内容总结 第十四章NIO与NIO2 NIO使用频道来衔接数据结点,在处理数据时,NIO可以让你设定缓冲 ...
- 仿QQ聊天图文混排流程图【适用于XMPP】
图文混排流程图.graffle4.8 KB 下面附上图片素材: 表情.zip692.5 KB 下面是字符串与图片的详细对应关系: "[呲牙]& ...
- 第9月第13天 传递lua匿名函数到c/c++
1. lua函数都在refid_fun refid_fun[refid] = fun TOLUA_API int toluafix_ref_function(lua_State* L, int lo, ...