j.u.c是java.util.concurrent的简称
通过查api,了解到是由以下这三个组成的。
juc包图
锁的两种实现方式
java并发编程,关于锁的实现方式有两种:
1.基于synchronized关键字实现同步,jvm内置锁,也叫隐式锁,由jvm自动加锁和解锁
2.juc下的lock接口实现的更加灵活的锁的实现方式,也叫显示锁,需要手动加锁和解锁
重要分类
locks部分:显示锁(互斥锁和读写锁)相关;
atomic部分:原子变量类相关,是构建非阻塞队列算法的基础,使用CAS实现;
executor部分:线程池相关;
collections部分:并发容器相关;
tools部分:同步工具相关,如信号量,闭锁,栅栏等;
lock图
ReentrantLock锁
ReentrantLock,可重入锁,是一种递归无阻塞的同步机制。
它可以等同于 synchronized的使用,但是 ReentrantLock 提供了比synchronized 更强大、灵活的锁机制,可以减少死锁发生的概率。
其中ReentrantLock里面涉及的公平锁与非公平锁;重入锁和非可重入锁。围绕着去实现的核心内在原理就是AQS抽象队列同步器。
里面ReentrantLock里面的变量
head 队列头
tail 队列尾
state 计数上锁次数
exlusiveOwnerThread 当前占有的线程
- ReentrantLock 实现 Lock 接口,基于内部的 Sync 实现(Sync是ReentrantLock的一个内部类)。
private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer {};
public ReentrantLock() {
sync = new NonfairSync();
}
- Sync 实现 AQS ,提供了 FairSync 和 NonFairSync 两种实现(NonfairSync和FairSync 的两个子类)。
static final class NonfairSync extends Sync {};
static final class FairSync extends Sync {};
condition
Condition 和 Lock 一起使用以实现等待/通知模式,通过 await()和singnal() 来阻塞和唤醒线程。
传送门
//一个条件队列的典型例子
while(!conditionPredition)
lock.wait();
doSomething();
Condition 是一种广义上的条件队列。
他为线程提供了一种更为灵活的等待 / 通知模式,线程在调用 await 方法后执行挂起操作,直到线程等待的某个条件为真时才会被唤醒。
Condition 必须要配合 Lock 一起使用,因为对共享状态变量的访问发生在多线程环境下。
一个 Condition 的实例必须与一个 Lock 绑定, Condition 一般是 Lock 的内部实现。
ReentrantReadWriteLock
读写锁维护着一对锁,一个读锁和一个写锁。
通过分离读锁和写锁,使得并发性比一般的排他锁有了较大的提升:1.在同一时间,可以允许多个读线程同时访问。
2.但是,在写线程访问时,所有读线程和写线程都会被阻塞。
特性:
- 公平性:支持公平性和非公平性。
- 重入性:支持重入。读写锁最多支持 65535 个递归写入锁和 65535 个递归读取锁。
- 锁降级:遵循获取写锁,再获取读锁,最后释放写锁的次序,如此写锁能够降级成为读锁。
ReentrantReadWriteLock 实现 ReadWriteLock 接口,可重入的读写锁实现类。
public class ReentrantReadWriteLock
implements ReadWriteLock, java.io.Serializable {
/** Inner class providing readlock */
private final ReentrantReadWriteLock.ReadLock readerLock;
/** Inner class providing writelock */
private final ReentrantReadWriteLock.WriteLock writerLock;
在同步状态上,为了表示两把锁,将一个 32 位整型分为高 16 位和低 16 位,分别表示读和写的状态
/*
* Read vs write count extraction constants and functions.
* Lock state is logically divided into two unsigned shorts:
* The lower one representing the exclusive (writer) lock hold count,
* and the upper the shared (reader) hold count.
*/
static final int SHARED_SHIFT = 16;
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
/** Returns the number of shared holds represented in count */
static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
原文地址:https://www.cnblogs.com/whyaza/p/12348215.html