Java concurrent programming --- ReentrantLock fair lock implementation principle

Java concurrent programming-ReentrantLock fair lock implementation principle

If a thread group can guarantee that each thread can obtain the lock, then the lock is a fair lock. On the contrary, if it is not guaranteed that every thread can get the lock, that is, there are threads starved to death, then the lock is an unfair lock.

First look at unfair locks

Insert picture description here

static final class NonfairSync extends Sync {
    
    
        final void lock() {
    
    
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }
    public final void acquire(int arg) {
    
    
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

Insert picture description here

        protected final boolean tryAcquire(int acquires) {
    
    
            return nonfairTryAcquire(acquires);
        }

The non-fair lock finally calls the nonfairTryAcquire method

        final boolean nonfairTryAcquire(int acquires) {
    
    
            final Thread current = Thread.currentThread();
            int c = getState();
            //如果还没有获得锁
            if (c == 0) {
    
    
            	//尝试用cas获得,这里体现了非公平性:不去检查AQS队列
                if (compareAndSetState(0, acquires)) {
    
    
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            //如果已经获得了锁,线程还是当前线程,表示发生`static final class FairSync extends Sync {了锁重入
            else if (current == getExclusiveOwnerThread()) {
    
    
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            //获取失败,回到调用处
            return false;
        }

Implementation of fair lock

static final class FairSync extends Sync {
    
    
final void lock() {
    
    
            acquire(1);
        }
    public final void acquire(int arg) {
    
    
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

Insert picture description here

		//与非公平锁主要区别在于tryAcquire方法的实现
        protected final boolean tryAcquire(int acquires) {
    
    
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
    
    
            	//先检查AQS队列中是否有前驱节点,没有才去竞争
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
    
    
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
    
    
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

This is hasQueuedPredecessors()not true before calling compareAndSetStateto grab the thread. If it is hasQueuedPredecessors()true, it means that there are other threads in the queue, and the following compareAndSetStatewill not be executed.
Note that it &&is a short-circuit operation.

	//判断队列中是否有一个前驱的节点
    public final boolean hasQueuedPredecessors() {
    
    
        Node t = tail; // Read fields in reverse initialization order
        Node h = head;
        Node s;
        // h != t 时表示队列中有Node
        return h != t &&
        	//情况一,(s = h.next) == null 表示队列中还没有老二
        	//情况二,队列中老二线程不是此线程        	
            ((s = h.next) == null || s.thread != Thread.currentThread());						
    }

The head is not equal to the tail, and there are nodes in the queue.
If there is no second child in the queue, if the second thread in the queue is not this thread, return true.
This means that there is a thread with a higher priority than you waiting in the queue, and it will not continue to execute the contention lock compareAndSetState(0, acquires)).

Reference

http://www.codeceo.com/article/reentrantlock-learn.html

Guess you like

Origin blog.csdn.net/e891377/article/details/104712266
Recommended