接下来跟着上一篇, 解析情景七和情景八
情景七
写写读
public static void main(String[] args) {
final Printer printer = new Printer();
Thread thread1 = new Thread(){
@Override
public void run() {
try {
printer.write("test1");
} catch (Exception e) {
e.printStackTrace();
}
}
};
Thread thread2 = new Thread(){
@Override
public void run() {
try {
printer.write("test2");
} catch (Exception e) {
e.printStackTrace();
}
}
};
Thread thread3 = new Thread(){
@Override
public void run() {
try {
printer.read("test3");
} catch (Exception e) {
e.printStackTrace();
}
}
};
thread1.start();
thread2.start();
thread3.start();
}
首先线程1开始
public void lock() {
sync.acquire(1);
}
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
protected final boolean tryAcquire(int acquires) {
// thread-0
Thread current = Thread.currentThread();
// c = 0
int c = getState();
// w = 0
int w = exclusiveCount(c);
// 不走此分支
if (c != 0) {
……
}
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires))
return false;
setExclusiveOwnerThread(current);
return true;
}
static final class FairSync extends Sync {
final boolean writerShouldBlock() {
return hasQueuedPredecessors();
}
}
public final boolean hasQueuedPredecessors() {
Node t = tail;
Node h = head;
Node s;
// 此时h和t都是null
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
说明此时队列中没有被阻塞的线程, hasQueuedPredecessors返回false
接下来回到tryAcquire方法
protected final boolean tryAcquire(int acquires) {
// thread-0
Thread current = Thread.currentThread();
// c = 0
int c = getState();
// w = 0
int w = exclusiveCount(c);
// 不走此分支
if (c != 0) {
……
}
// writerShouldBlock返回false
// 不走此分支
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires))
return false;
// 设置获得写锁的线程为thread-0
setExclusiveOwnerThread(current);
return true;
}
此时线程1已经获取到锁, 接下来线程2开始执行
// WriteLock
public void lock() {
sync.acquire(1);
}
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
protected final boolean tryAcquire(int acquires) {
// Thread-1
Thread current = Thread.currentThread();
// c = 1
int c = getState();
// w = 1
int w = exclusiveCount(c);
if (c != 0) {
// 由于加锁线程为thread-0, 非当前线程
// 进此分支
if (w == 0 || current != getExclusiveOwnerThread())
return false;
......
}
......
}
回到acquire方法
public final void acquire(int arg) {
// 此时tryAcquire方法返回false
// 之后线程会缓存渔队列中并阻塞自己
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
线程3开始执行
// ReadLock
public void lock() {
sync.acquireShared(1);
}
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
protected final int tryAcquireShared(int unused) {
// thread-2
Thread current = Thread.currentThread();
// c = 1
int c = getState();
// 由于已经加写锁, 所以exclusiveCount(c)为1
if (exclusiveCount(c) != 0 &&
// 并且加写锁线程不是当前线程
// 走此分支
getExclusiveOwnerThread() != current)
// 返回
return -1;
......
}
返回acquireShareShared
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
// 将该线程加入队列中
// 并阻塞自己
doAcquireShared(arg);
}
情景八
写写写
所有经历的代码都分析过, 线程2和线程3都会被阻塞