ReadWriteLock之公平锁解析(四)

接下来跟着上一篇, 解析情景七和情景八

情景七

写写读

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都会被阻塞

你可能感兴趣的:(ReadWriteLock之公平锁解析(四))