美文网首页
ReadWriteLock之公平锁解析(四)

ReadWriteLock之公平锁解析(四)

作者: 436048bfc6a1 | 来源:发表于2021-11-23 16:36 被阅读0次

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

情景七

写写读

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之公平锁解析(四)

    接下来跟着上一篇, 解析情景七和情景八 情景七 写写读 首先线程1开始 说明此时队列中没有被阻塞的线程, hasQ...

  • ReadWriteLock之公平锁解析(三)

    接下来跟着上一篇, 解析情景五和情景六 情景五 写读读 回到tryAcquire方法 此时线程1获得写锁, 线程2...

  • ReadWriteLock之公平锁解析(一)

    接下来探讨ReadWriteLock的公平锁实现, 也是分如下场景分析 情景1 三个线程都是读 接下来回到tryA...

  • ReadWriteLock之公平锁解析(二)

    接下来跟着上一篇, 解析情景三和情景四 情景三 读写读 线程1的获得读锁的操作和情景一相同, 接下来从线程2开始分...

  • 一张图读懂非公平锁与公平锁

    在Java并发编程中,公平锁与非公平锁是很常见的概念,ReentrantLock、ReadWriteLock默认都...

  • ReadWriteLock读写锁

    1、引入ReadWriteLock读写锁 ReadWriteLock是JDK5中提供的读写分离锁。读写分离锁可以有...

  • ReadWriteLock

    ReadWriteLock 从这一节开始介绍锁里面的最后一个工具:读写锁(ReadWriteLock)。 Reen...

  • java初入多线程9

    ReadWriteLock 多写锁 ReadWriteLock 是JDK5中提供的读写分离锁,读写分离可以有效的帮...

  • JUC(九) -ReadWriteLock 读写锁

    9. ReadWriteLock 读写锁 ReadWriteLock 维护了一对相关的锁,一个用于只读操作,另一个...

  • Java锁 - 导读

    目录 常用锁 synchronized ReentrantLock ReadWriteLock Semaphore...

网友评论

      本文标题:ReadWriteLock之公平锁解析(四)

      本文链接:https://www.haomeiwen.com/subject/ivebtrtx.html