JUC-ReentrantLock source code

First upload the source code

public class ReentrantLock implements Lock, java.io.Serializable {
    
    
    private static final long serialVersionUID = 7373984872572414699L;

    // 内部使用的同步器
    private final Sync sync;

    // 构造函数,可以选择公平或非公平锁,默认为非公平锁
    public ReentrantLock() {
    
    
        sync = new NonfairSync();
    }

    public ReentrantLock(boolean fair) {
    
    
        sync = fair ? new FairSync() : new NonfairSync();
    }

    // 获取锁
    public void lock() {
    
    
        sync.lock();
    }

    // 可中断的获取锁
    public void lockInterruptibly() throws InterruptedException {
    
    
        sync.acquireInterruptibly(1);
    }

    // 尝试获取锁,成功返回true,失败返回false
    public boolean tryLock() {
    
    
        return sync.nonfairTryAcquire(1);
    }

    // 带超时时间的尝试获取锁,成功返回true,失败返回false
    public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
    
    
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }

    // 释放锁
    public void unlock() {
    
    
        sync.release(1);
    }

    // 返回一个Condition对象
    public Condition newCondition() {
    
    
        return sync.newCondition();
    }

    // 获取当前线程持有锁的个数
    public int getHoldCount() {
    
    
        return sync.getHoldCount();
    }

    // 判断当前线程是否持有锁
    public boolean isHeldByCurrentThread() {
    
    
        return sync.isHeldExclusively();
    }

    // 判断锁是否被任意线程持有
    public boolean isLocked() {
    
    
        return sync.isLocked();
    }

    // 获取同步器
    public final Sync getSync() {
    
    
        return sync;
    }

    // 抽象同步器
    abstract static class Sync extends AbstractQueuedSynchronizer {
    
    
        private static final long serialVersionUID = -5179523762034025860L;

        // 加锁
        abstract void lock();

        // 尝试非公平获取锁
        final boolean nonfairTryAcquire(int acquires) {
    
    
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
    
    
                if (compareAndSetState(0, acquires)) {
    
    
                    setExclusiveOwnerThread(current);
                    return true;
                }
            } 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;
        }

        // 尝试获取锁,可响应中断
        final void acquireInterruptibly(int arg) throws InterruptedException {
    
    
            if (Thread.interrupted())
                throw new InterruptedException();
            if (!tryAcquire(arg))
                doAcquireInterruptibly(arg);
        }

        // 尝试获取锁,可响应中断和超时
        final boolean tryAcquireNanos(int arg, long nanosTimeout) throws InterruptedException {
    
    
            if (Thread.interrupted())
                throw new InterruptedException();
            return tryAcquire(arg) || doAcquireNanos(arg, nanosTimeout);
        }

        // 释放锁
        protected final boolean tryRelease(int releases) {
    
    
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
    
    
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

        // 是否独占锁
        final boolean isHeldExclusively() {
    
    
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        // 条件变量
        final ConditionObject newCondition() {
    
    
            return new ConditionObject();
        }

        // 获取当前线程持有锁的个数
        final int getHoldCount() {
    
    
            return isHeldExclusively() ? getState() : 0;
        }

        // 非公平锁同步器
        static final class NonfairSync extends Sync {
    
    
            private static final long serialVersionUID = 7316153563782823691L;

            // 加锁
            final void lock() {
    
    
                if (compareAndSetState(0, 1))
                    setExclusiveOwnerThread(Thread.currentThread());
                else
                    acquire(1);
            }

            // 尝试获取锁
            protected final boolean tryAcquire(int acquires) {
    
    
                return nonfairTryAcquire(acquires);
            }
        }

        // 公平锁同步器
        static final class FairSync extends Sync {
    
    
            private static final long serialVersionUID = -3000897897090466540L;

            // 加锁
            final void lock() {
    
    
                acquire(1);
            }

            // 尝试获取锁
            protected final boolean tryAcquire(int acquires) {
    
    
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
    
    
                    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;
            }
        }
    }
}

ReentrantLock is a reentrant lock in Java that provides the same mutual exclusion and memory visibility as synchronized, but it is more flexible than synchronized and can implement more advanced functions, such as fair locks, interruptible locks, multiple condition variable etc.

The following is a summary of the source code analysis of ReentrantLock:

  1. ReentrantLock is a reentrant lock, which represents the state of the lock through a state variable of type int, where the high 16 bits represent the number of threads holding the lock, and the low 16 bits represent the number of reentrants of the current thread.

  2. ReentrantLock supports fair locks and unfair locks, and the default is unfair locks. Fair locks will acquire locks in the order in which threads request locks, while unfair locks will give priority to threads already waiting in the queue, which may cause new threads to jump in the queue to acquire locks.

  3. ReentrantLock supports interruptible locks, that is, it can respond to interrupt signals during the process of waiting for locks, which is realized by calling the lockInterruptibly() method.

  4. ReentrantLock supports multiple condition variables, implemented through the Condition interface. Each ReentrantLock object can create multiple Condition objects to implement different waiting/notification mechanisms.

  5. ReentrantLock internally uses AQS (AbstractQueuedSynchronizer) to implement the lock synchronization mechanism. AQS is an abstract class that provides some basic synchronization operations, such as acquiring locks, releasing locks, waiting queues, etc. ReentrantLock uses AQS template methods to implement its own synchronization logic.

  6. The lock() method and unlock() method of ReentrantLock are the core methods of ReentrantLock, and they realize the acquisition and release of locks by calling the acquire() and release() methods of AQS. In the lock() method, if the current thread already holds the lock, directly increase the number of reentries; otherwise, acquire the lock through the acquire() method of AQS. In the unlock() method, if the current thread still holds the lock, reduce the number of reentries; otherwise, release the lock through the release() method of AQS.

  7. The tryLock() method of ReentrantLock is a non-blocking method for trying to acquire a lock, and it will immediately return the result of acquiring the lock without blocking the current thread. Returns true if the lock was acquired successfully; otherwise, returns false.

  8. The tryLock(long timeout, TimeUnit unit) method of ReentrantLock is a method with a timeout to try to acquire a lock. It will try to acquire a lock within the specified time. If the lock is acquired successfully, it returns true; otherwise, it returns false.

  9. The lockInterruptibly() method of ReentrantLock is an interruptible method of acquiring a lock. It will respond to an interrupt signal while waiting for the lock. If the current thread is interrupted, an InterruptedException will be thrown.

  10. The Condition interface of ReentrantLock provides a waiting/notification mechanism, which allows threads to enter the waiting state when waiting for a certain condition to be established, and be woken up when the condition is established. The implementation class of the Condition interface is ConditionObject, which is an internal class of AQS, and is used to realize the management of the waiting queue and the wake-up of threads.

To sum up, ReentrantLock is a very powerful and flexible lock that provides many advanced functions to meet different synchronization needs. However, due to its complex implementation, some details need to be paid attention to when using it to avoid problems such as deadlock and starvation.

Guess you like

Origin blog.csdn.net/weixin_47763579/article/details/131145408