十三、显式锁
1)Lock与ReentrantLock
-
void lock(); 获取锁,未获取到则阻塞。
-
void lockInterruptibly() throws InterruptedException; 获取锁,未获取到则阻塞,阻塞可中断。
-
boolean tryLock(); 获取锁,返回是否获取到
-
boolean tryLock(long time, TimeUnit unit) throws InterruptedException; 获取锁,不能立即获取,则阻塞time时间,返回是否获取到。
-
void unlock(); 释放锁。
-
Condition newCondition(); 构建一个Condition条件,用于实现await、signal、signalAll 等待唤醒。
2)公平性
ReentrantLock支持公平锁与非公平锁,默认非公平。
-
公平锁:获取锁时,如果锁被其他线程占用,则直接去排队挂起。
-
非公平锁:获取锁时,如果锁被其他线程占用,先尝试获取一次,获取失败就去排队。
3)synchronize与ReentrantLock的选择
在jdk1.8中,synchronize与ReentrantLock的性能差别不大,优先选择使用synchronize,当在一些功能上(锁超时、条件等待、可中断、公平性)不能满足时,再使用ReentrantLock。
synchronize锁可通过jstack查看持有线程,也可以检索死锁,但ReentrantLock做不到。
十四、构建自定义同步工具
1)AQS
//AQS同步器维护的状态
private volatile int state;
//AQS中维护的等待链表,head头结点,tail尾结点
private transient volatile Node head;
private transient volatile Node tail;
//tryAcquire子类实现,判断当前state是否可做申请操作,返回true/false
//acquireQueued在tryAcquire返回false时执行,将线程封装成node放入队列并挂起线程,返回是否中断
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
//tryRelease子类实现,判断当前状态是否可做释放操作,返回true/false
//unparkSuccessor唤醒head节点之后第一个状态为-1的节点中的线程
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
//tryAcquireShared子类实现,判断是否可做申请操作,返回int,小于0不可操作
//doAcquireShared将线程封装成node放入队列并挂起线程
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
//tryReleaseShared子类实现,判断是否可做释放操作,返回true/false
//doReleaseShared唤醒所有等待链表状态为-1节点的线程
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
//子类实现,在排他模式下,判断状态是否被占用
protected boolean isHeldExclusively();
2)并发包下的AQS
-
ReentrantLock
-
-
state记录了锁重入次数,并且还维护了owner线程
-
tryAcquire做state累加,state = 0未占用,state = N,被owner lock了N次,且做了owner的可重入判断。
-
tryRelease做了state减少,到0清理owner。
-
isHeldExclusively判断是不是当前线程。
-
-
Semaphore
-
-
state维护了许可证数。
-
tryAcquireShared做state减少,返回(当前-申请)。
-
tryReleaseShared做state增加。
-
-
CountDownLatch
-
-
state维护了需要count次数。
-
tryAcquireShared判断state是否为0,为0则返回1,否则返回-1,await调用acquireShared。
-
tryReleaseShared做state减少,每次减1,当减少到0是,返回true,否则返回false,countDown调用releaseShared。
-
-
ReentrantReadWriteLock
-
-
state维护一个32位的数,高16位维护读锁线程数,低16位维护锁重入次数。
-
tryAcquire 操作state低位增加,有读线程占着读锁||有其他线程占着写锁 返回false;其他情况增加state,且设置wtire线程。
-
tryRelease 操作state低位减少,低位减少到0返回true,且设置write线程为null。
-
tryAcquireShared 操作state高位增加,当前有其他线程的写锁返-1,否则高位加1返1。
-
tryReleaseShared 操作state高位减少,高位减1,减少整体为0,则返回true。
-