目录
锁
定义
package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
public interface Lock {
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
}
优点
- 持续等待-lock()
- 可中断-lockInterruptibly()
- 非阻塞-tryLock() 没有公平可言!
- 可超时-tryLock(long time, TimeUnit unit)
- 非阻塞块使用
- 任意链式锁:a+、b+、c+、a-、c-、b-
缺点
- 有使用要求
Lock l = ...;
l.lock();
try {
// access the resource protected by this lock
} finally {
l.unlock();
}}
特点
-
定义了锁的基本使用需求方法:独占(如定时任务)或者保持时序(如计时器)
-
普通接口+普通实现类:意味着任何人都可以实现
-
纯code实现,没有特殊的JVM底层支持
-
提供了抽象支持AbstractQueuedSynchronizer
如何实现
- 使用一个标志位表示锁是否被获取
- 使用一个数据结构保存等待的线程
AbstractQueuedSynchronizer
- 使用int表示状态,支持重入
- 使用CLH变种队列实现等待队列:双向链表,pre可靠,状态保存在前继节点中,有虚拟头节点
- 支持独占和共享模式
- 使用LockSupport进行线程阻塞
状态变量
- 使用int表示状态,更具拓展性
CLH队列
- 使用反向单链表实现
- 公平锁
- 不断自旋,获取前继节点状态
- CLH详情链接
独占模式和共享模式
- 独占模式只支持一个线程获取锁:ReentrantLock
- 共享模式支持多个线程同时获取锁:Semaphore
LockSupport
- park 阻塞线程
- unpark 取消阻塞线程
AQS实现-ReentrantLock
-
可重入,独占模式
-
通过Sync继承AbstractQueuedSynchronizer,实现独占获取和释放
-
Sync具体实现分为公平和非公平两种,区别在于获取时是否能插队
-
ReentrantLock实现Lock接口,具体实现调用Sync
公平锁
lock细节
- 没人排队,尝试获取锁
- 自己在排队,重入
- 别人在排队,自己进入队列,设置pre状态,park
unlock细节
- 必须是获得锁的线程,不然报错
- 释放状态,如果完全释放,解除独占线程
- 如果完全释放,唤醒第一个等待线程
AQS实现-Semaphore
- 不可重入,共享模式
- 初始化一个状态值,获取时判断状态值是否超过最大值,超过获取失败,不超过获取成功
AQS实现-CountDownLatch
- 初始化一个状态值,每次countDown的时候释放1
- await等待获取锁,当countDown完成后,await获取锁成功