Genlock --ReentrantLock


This blog series is to learn the process of recording concurrent programming summarized. As more articles written by time is relatively loose, so I put together a catalog paste (portal) for easy access.

Concurrent Programming Series blog portal


Lock Interface Overview

In the JUC package below a java.util.concurrent.lockspackage, which provides a range of tools based lock on the synchronization mechanism traditional synchronizd, wait and notify like complement and enhance. Here's start with the Lock interface.

LockThe interface can be seen as synchronizedan enhanced version provides a more flexible functionality. With respect to synchronized, Lockthe interface also provides a limit lock wait, lock interrupt and try to lock functions. The interface is defined as follows


public interface Lock {
// 尝试去获得锁
// 如果锁不可用,当前线程会变得不可用,直到获得锁为止。(中途会忽略中断)    
void lock();

// 尝试去获取锁,如果锁获取不到,线程将不可用
// 知道获取锁,或者被其他线程中断
// 线程在获取锁操作中,被其他线程中断,则会抛出InterruptedException异常,并且将中断标识清除。
void lockInterruptibly() throws InterruptedException;

// 锁空闲时返回true,锁不空闲是返回false
boolean tryLock();

// 在unit时间内成功获取锁,返回true
// 在unit时间内未成功获取锁,返回false
// 如果当前线程在获取锁操作中,被其他线程中断,则会抛出InterruptedException异常,并且将中断标识清除。
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

// 释放锁
void unlock();

// 获取一个绑定到当前Lock对象的Condition对象
// 获取Condition对象的前提是当前线程持有Lock对象
Condition newCondition();
}

On the above lock () and lockInterruptibly in () method, with the following differences:

lock () method is similar to using the synchronized keyword lock if the lock is not available for thread scheduling purposes, the current thread becomes disabled, and before acquiring the lock, the thread has been in a dormant state.
lockInterruptibly () method As the name suggests, is that if the lock is not available, then the thread is currently waiting can be interrupted, which is more flexible than the synchronized keyword.

Classic Lock interface usage

Lock lock = new ReentrantLock();
if (lock.tryLock()) {
    try {
        // manipulate protected state
    } finally {
        lock.unlock();
    }
} else {
    // perform alternative actions
}

ReentrantLock

ReentrantLockClass is a reentrant exclusive lock, in addition to having the same functions and synchronized, further comprising a lock wait limit, and the latch lock attempt interrupt functions.

ReentrantLockThe bottom layer is to achieve an exclusive lock function through inheritance AQS.

Fair and unfair lock lock

About ReentrantLock, there are two very important concepts to learn: fair and unfair lock lock .

View ReentrantLockthe source code, we will see two constructors, the corresponding structure is divided into equity and non-equity lock lock.

//默认构造非公平锁
public ReentrantLock() {
    sync = new NonfairSync();
}
//true构造公平锁,false构造非公平锁
public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

Fair locks : refers to the thread after the failure to seize the lock goes into a queue, the queue to enter the thread will first obtain a lock. Fairness reflect a first-come basis.
Unfair lock : is the thread to seize the lock failure will enter a waiting queue, but those who can wait for a thread to acquire the lock is not in accordance with the rules of first come first served, but random. Unfairness is reflected in the subsequent thread may get a lock first.

If there are many threads fair competition in a lock, the overall throughput of the system (that is, very slow, often extremely slow) is relatively low, because the overhead thread scheduling above is relatively large.

The reason is that when using fair tactics, when a thread releases the lock, you need to first wait queue thread wakes up. The wake-up scheduling process is more time-consuming. If you use a non-arm lock, then, when a thread releases the lock, the thread can be used immediately acquire the lock, higher efficiency.

ReentrantLock code implementation

1. lock code is unfair

static final class NonfairSync extends Sync {

    private static final long serialVersionUID = 7316153563782823691L;

    /**
     * Performs lock.  Try immediate barge, backing up to normal
     * acquire on failure.
     */
    final void lock() {
        //如果没有线程占据锁,则占据锁,也就是将state从0设置为1
        //这种抢占方式不要排队,有人释放了锁,你可以直接插到第一位
        //去抢,只要你能抢到
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
        //否则尝试抢占锁
            acquire(1);
    }

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

By Before the introduction of AQS, we know when to seize the lock will call tryAcquire method. Unfair lock this method to directly call the parent class nonfairTryAcquire.


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;
}

1. Lock Code fair


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;
        }
    }

Guess you like

Origin www.cnblogs.com/54chensongxia/p/12360824.html