怎么拥抱她终究要飞翔
文章目录
1. 继承关系
Serializable
接口不必多说Lock
接口六个方法:
public interface Lock {
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
}
思考①:
lockInterruptibly
是何方妖孽?存在意义是什么?
顾名思义就是可中断的加锁。在加锁的过程中是可能会在队列中等待的,如果此过程不能被中断,那这个线程在成功加锁之前就无法被优雅结束了。所谓优雅,就是在结束之前能做一些资源释放之类的,而不是不计后果直接kill。
那可不可以用别的方法?肯定是有,但是大体思路和中断基本是一致的。详细有一个线程在等待队列中,现在我们要取消它,那做法有两种:
- 取队列里找到它,更新队列状态
- 更新线程的状态,等它执行的时候自己做判断
显然第一种实现起来麻烦很多,第二种就简单多了,而只要采用第二种思路,就会用一个类似标志位的东西,那思路就和中断异常一致了。
思考②:
Condition
是嘛?
这属于MESA模型的概念,借用《极客时间》王宝令老师的一张图,感兴趣的小伙伴可以自己去看一下
2. 内部类
2.1 Sync
继承AQS
abstract static class Sync extends AbstractQueuedSynchronizer{
。。。}
非公平方式获取锁
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
// 获取同步器状态,也就是加载同步器上的锁的层数,如果是0,表示锁可用
// 同步器概念约等于锁
int c = getState();
// 如果同步器状态可用,则尝试获取
if (c == 0) {
// CAS获取锁
if (compareAndSetState(0, acquires)) {
// 该方法属于AbstractOwnableSynchronizer定义的,就是设置同步器的当前
// 所属线程
setExclusiveOwnerThread(current);
return true;
}
}
// 当同步器上的锁是当前线程加上的,也就是重入的情况
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
// 可重入锁最多可以加Integer.MAX_VALUE层
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
为什么说是非公平的?
该方法在判断同步器状态为可用时就立即以CAS方式尝试获取锁,但是此时可能等待队列中存在等待节点。
尝试释放锁
protected final boolean tryRelease(int releases) {
// c为此次释放后,剩余的锁层数
int c = getState() - releases;
// 只有锁的持有线程才可以释放锁
if (Thread.