重入锁ReentrantLock

52 阅读2分钟

重入锁ReentrantLock

what:

支持可重入的锁,并且支持获取锁时的公平和非公平性选择.

why:

不支持重进入的锁,没有考虑当前占有锁的线程再次获取锁的场景,tryAcquire第一次是true第二次就是false.

how:

1.线程再次获取锁.

锁需要识别获取锁的线程是否为当前占有的线程,如果是,再次获取成功.

2.锁的最终释放.

线程重复n次获取了锁,随后在第n次释放该锁后,其他线程能够获取到该锁.锁的最终释放要求锁对于获取进行计数自增,计数表示当前锁被重复获取的次数,而锁被释放时,计数自减,当计数等于0时表示锁已经成功释放.

具体实现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)
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;//返回true表示获取同步状态成功
        }
    return false;
}

释放具体实现tryRelease方法

protected final boolean tryRelease(int releases){
    int c = getState()-releases;
    if(Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    if(c == 0){//同步状态为0,全部已经释放
        free = true; //设置状态为free
        setExclusiveOwnerThread(null); //当前占有线程为空
    }
    setState(c);
    return free;
}

公平锁

what:

绝对时间上,先对锁获取的请求一定先满足,这个锁就是公平的.锁获取的顺序一定是FIFO的

how:

ReentrantLock的tryAcquire方法

protected final boolean tryAcquire(int acquires){
    final Thread current = Thread.currentThread();
    int c = getState();
    if(c == 0){
        //与非公平方式获取锁的主要区别是,要判断是否有前驱节点,没有才能获取成功
        if(!hasQueuedProdeccessor() && 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;
}