参考链接
1 AQS (AbstractQuenedSynchronizer)
- AQS 维护状态
volatile int state (ReentrantLock 将它作为锁的重入次数)和一个 FIFO 的线程等待队列,多线程争用资源被阻塞的时候就会进入这个队列;队列头部的线程执行完毕之后,它会调用它的后继的线程 - 线程通过 CAS 改变状态符 state,成功则获取锁成功,失败则进入等待队列,等待被唤醒
- AQS 采用 自旋锁 的机制
2 ReentrantLock 非公平锁加锁流程
- 非公平锁是指新来的线程跟 AQS 队列头部的线程竞争锁,队列其他的线程还是正常排队
- 公平锁严格执行 FIFO,新线程只能加入队尾
- 非公平锁尝试加锁,即执行
tryAcquire() 的流程是:检查state字段,若为0,表示锁未被占用,尝试占用锁;若不为0,检查当前锁是否被自己占用,若被自己占用,则更新 state 字段,重入次数加 1 - 如果以上两点都没有成功,则获取锁失败,进入等待队列
- 进入等待队列的线程尝试获取锁(最靠前的线程才有资格尝试),如果获取成功则成为队列新的头节点,获取失败则尝试挂起
- 线程入队后能够挂起的前提是,它的前驱节点的状态为 SIGNAL,状态为 SIGNAL 的节点在出队后会唤醒后面紧邻的节点
3 ReentrantLock 和 synchronized 的异同
- 响应中断:如果某一线程A正在执行锁中的代码,另一线程B正在等待获取该锁,可能由于等待时间过长,线程B不想等待了,想先处理其他事情,我们可以让它中断自己或者在别的线程中中断它,这种就是可中断锁。Lock 等待锁过程中可以用interrupt 来中断等待
- 超时等待:规定超时等待时间,避免线程无限期的等待锁释放
- 公平锁与非公平锁:公平锁是指多个线程同时尝试获取同一把锁时,获取锁的顺序按照线程达到的顺序,而非公平锁则允许线程“插队”,具体是新来的线程和队首的线程竞争锁
|