程序员计算机技术

Java并发-重入锁ReentrantLock

2019-02-28  本文已影响3人  油多坏不了菜

基础

基本使用

ReentrantLock lock = new ReentrantLock();//非公平锁
//ReentrantLock lock = new ReentrantLock(true);//公平锁
        lock.lock();
        try{
            //to do
        }finally {
            lock.unlock();
        }

ReentrantLock的基本骨架

ReentrantLock implements Lock{
private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer {......};
static final class NonfairSync extends Sync {};//非公平锁用这个同步器
static final class FairSync extends Sync {};//公平锁用这个同步器
}
public ReentrantLock(boolean fair) {//选择是公平锁还是非公平锁
     sync = fair ? new FairSync() : new NonfairSync();
}
public ReentrantLock() {//默认为非公平锁
        sync = new NonfairSync();
}

源码角度分析其可重入性和公平性的实现

可重入特性实现(非公平锁为例)

锁的获取

如果当前同步状态已经被线程获取(state != 0),判断当前尝试获取同步状态的线程是否是已经获取同步状态的线程,如果是就代表当前线程重入获取锁,将同步状态的值增加(所以获取锁多少次,就应该释放锁多少次),返回成功。

 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;
        }
锁的释放

因为同步状态的获取可能获取了n次,所以应该只有最后一次释放之后才应该返回true(线程已释放锁)。

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

公平性实现

用户层面而言:锁的获取严格遵守FIFO模式
源码角度来说:公平锁的tryAcquire与非公平锁不同之处在于---公平锁如果判断锁空闲,还需要去判断同步队列中有没有在排队的(非公平锁没有这一步),如果有的话就去同步队列中排队。

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;
        }
上一篇 下一篇

猜你喜欢

热点阅读