ReenTrantLock重入锁

ReenTrantLock(重入锁)

非公平性锁(默认):不是按照先后顺序,而是按照抢占式来获得锁,
公平性锁(false):按照线程请求锁的顺序来获取锁

具体的剖析:

ReenTrantLock实现Lock和序列化接口
三个内部类:ync、NonfairSync、FairSync
抽象类Sync继承了 AbstractQueuedSynchronizer(AQS)类
构造函数:

 ReentrantLock() {   //无参构造创建一个 ReentrantLock 的实例,默认的是非公平性锁
    sync = new NonfairSync();
}
       
     ReentrantLock(boolean fair){  //创建一个具有给定公平策略的 ReentrantLock,默认true采用非公平性锁
 sync = fair ? new FairSync() : new NonfairSync();
      }

基本操作方法:
● public void unlock() {
当前线程的锁的释放,每次释放锁对state-1,当state为0的时候才是真正的释放锁
● isHeldByCurrentThread()
查询当前线程是否获取此锁。
● final Thread getOwner()
返回目前获取此锁的线程,
● boolean hasQueuedThreads()
查询是否有线程正在等待获取锁
● boolean hasQueuedThread()
判断传进来的线程是否处于阻塞队列中
● boolean hasWaiters(Condition condition)
判断当前condition的实例是否处于wait状态
● public int getHoldCount()
当前线程获取锁的次数

AbstractQueuedSynchronizer(很重要)
基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架。该同步器(以下简称同步器)利用了一个int来表示状态。同步器的开始提到了其实现依赖于一个FIFO队列,那么队列中的元素Node就是保存着线程引用和线程状态的容器,每个线程对同步器的访问,都可以看做是队列中的一个节点。
Node的主要包含以下成员变量:

Node {
    int waitStatus;//节点的状态
    Node prev;//前驱节点
    Node next;//后继节点
    Node nextWaiter;//存储condition队列中的后继节点
    Thread thread;//入队列时的当前线程
}

表示节点的状态。其中包含的状态有:
CANCELLED,值为1,表示当前的线程被取消;
SIGNAL,值为-1,表示当前节点的后继节点包含的线程需要运行,也就是unpark;
CONDITION,值为-2,表示当前节点在等待condition,也就是在condition队列中;
PROPAGATE,值为-3,表示当前场景下后续的acquireShared能够得以执行;
值为0,表示当前节点在sync队列中,等待着获取锁。

AQS: AbstractQueuedSynchronizer(没有获取到锁的线程放入队列中)
没有获得锁的线程,就存放在AQS队列中
AQS类中的state:
state=0; 表示锁是空闲的状态
state>0;表示锁被占用
state<0;表示溢出
重入锁的实现: 当前线程每获取一次锁state就进行+1操作,每次释放锁对state减一,当state=0时才是真正释放锁

锁的相关方法

sync中的操作:

获取锁的方法:
abstract void lock();

 boolean nonfairTryAcquire:
        final boolean nonfairTryAcquire(int acquires) {//获取当前的线程
            final Thread current = Thread.currentThread();//获取锁的状态
            int c = getState();
            if (c == 0) {//表示当前锁空闲,成功获取则将state置为1,并且将当前线程记录下来,直接返回
                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);//若没有到达上限则直接更新state
                return true;
            }
            return false;//当前获取锁的线程非当前的线程,则返回false
        }

释放锁操作
boolean tryRelease:

        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())//获取锁的线程非当前的线程,则直接抛出异常
                throw new IllegalMonitorStateException();
            boolean free = false;//当state减1为0时,才是将锁真正的释放,然后将获取锁的线程置为null
            if (c == 0) {//当state减为1的情况下,释放了锁
                free = true;
                setExclusiveOwnerThread(null);//将当前获取锁的线程置为null
            }
            setState(c);
            return free;
        }

NonfairSync中的操作:

1、第一次通过CAS强制抢锁,抢锁失败则再次尝试性抢锁
2、第二次尝试性抢锁,首先判断锁是否未占用(state=0),是则直接CAS来获取锁,
获取成功则修改state,且将当前线程计入AQS中,成功返回
在判断锁占用的情况下,占用锁的线程是当前线程,则直接修改state,成功返回
以上都不满足,失败返回
3、若失败返回,则当前线程未获取到锁,则即将线程加入AQS中的队列
void lock

        final void lock() {
            if (compareAndSetState(0, 1))//抢锁
                setExclusiveOwnerThread(Thread.currentThread());//获取锁成功
            else
                acquire(1);//获取失败,将线程放置等待队列中
        }
boolean tryAcquire
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);//再次进行获取锁
        }
    }

FairSync中的操作:

1、尝试性获取锁
若锁未被占用,判断当前线程是否满足条件(AQS队列为空或者当前线程处于AQS队列的队头),修改state,将当前线程记录到锁上,成功返回
若锁被占用,且是当前线程占有锁,修改state,成功返回
若以上都不满足,则失败返回
2、若未获取到锁,则即将线程加入AQS中的队列
boolean tryAcquire

        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {//当前的队列为空,或者当前线程处于队列的first的node
                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;
        }
    }

AQS中的:
void acquire

  public final void acquire(int arg) {
        if (!tryAcquire(arg) &&   //如果tryAcquire为false将它直接放入到队列中
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
 boolean hasQueuedPredecessors
    public final boolean hasQueuedPredecessors() {
        Node t = tail;
        Node h = head;
        Node s;
        return h != t &&//头节点和尾节点不相等,队列不为空
            ((s = h.next) == null || s.thread != Thread.currentThread());//只有一个节点或者当前线程不等于头节点储存的线程
    }

**公平性锁和非公平性锁的区别点:**主要是lock的方法上不同
1,抢锁的次数不一样
2,判断获取锁的线程是否在队

你可能感兴趣的:(Java)