Analysis of put source code in LinkedBlockingQueue

View the source code to know:

LinkedBlockingQueue adopts the technology of lock separation

    // remove the lock
    private final ReentrantLock takeLock = new ReentrantLock();

    // remove the lock condition
    private final Condition notEmpty = takeLock.newCondition();

    //insert lock
    private final ReentrantLock putLock = new ReentrantLock();

    //insert lock condition
    private final Condition notFull = putLock.newCondition();

View the put method source code

public void put(E e) throws InterruptedException {
        // check that the element is empty
        if (e == null) throw new NullPointerException();
        //set element value
        int c = -1;
        //create node
        Node<E> node = new Node<E>(e);
        //Acquire insert lock
        final ReentrantLock putLock = this.putLock;
        //set the number
        final AtomicInteger count = this.count;
        // try to lock
        putLock.lockInterruptibly();
        try {
            // Judging if this number is equal to the number of containers, the container is full
            while (count.get() == capacity) {
                //wait
                notFull.await();
            }
            //insert
            enqueue(node);
            //length+1
            //The c obtained here should be the original data, getAndIncrement is equivalent to i++
            c = count.getAndIncrement();
            / / Determine whether it is less than the container volume after +1
            if (c + 1 < capacity)
                // Less than, notify other insert threads to insert
                notFull.signal();
        } finally {
            //unlock
            putLock.unlock();
        }
        //If c==0 means there was no element, now there is an element
        //So the wait in its queue must be released
        if (c == 0)
            signalNotEmpty();
    }

  Among them, this source code has been understood for a long time: why do you want to add this sentence?

if (c == 0)
            signalNotEmpty();

 Since c acquires the data before adding the element, it is judged to be 0, which means that the queue was empty before, resulting in the thread in the take method being in a waiting state. This method can release the waiting thread in the take method, so that it can Obtain resources, as follows c is the original queue length obtained

//The c obtained here should be the original data, getAndIncrement is equivalent to i++
            c = count.getAndIncrement();
signalNotEmpty方法      private void signalNotEmpty() {
     // get the lock
        final ReentrantLock takeLock = this.takeLock; 
     //Because the notification operation needs to be performed later, the lock must be acquired first takeLock.lock(); try {
       //Notify that there are elements in the queue now, you can get the elements notEmpty.signal(); } finally {
       //unlock takeLock.unlock(); } }

  

  

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325059829&siteId=291194637