[java 并发] ReentrantLock公平锁和非公平锁的实现

reentrantlock可以实现公平锁和非公平锁

   ReentrantLock lock=new  ReentrantLock(false);
   
   public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

非公平锁中源码如下

    final void lock() {
        // 如果cas尝试获取锁成功(将state锁状态从0设置为1)
           if (compareAndSetState(0, 1))
               //设置当前线程为独占锁的线程
              setExclusiveOwnerThread(Thread.currentThread());
           else
              acquire(1);
    }
    public final void acquire(int arg) {
        //如果获取失败返回false 会继续执行将当前线程链入队尾并挂起
        if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();//中断自己
    }
final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
    		//获取锁状态
            int c = getState();
            if (c == 0) {
                //如果当前没有线程在使用,直接使用cas尝试获取锁,新的线程可能抢占已经排队的线程的锁的使用权,
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);// 设置当前线程独占锁
                    return true;
                }
            }
		    //如果不为0则判断当前线程是不是独占锁的线程
            else if (current == getExclusiveOwnerThread()) {
                // 如果是将锁数量状态值+1(可重入锁来源)
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
		    //请求即没有获取到锁,也不是当前独占锁的线程,返回false
            return false;
       }

非公平锁主要就是线程来了之后就进行抢占锁的操作,不管队列中是否有排队的线程与否
我整理的流程图如下
[java 并发] ReentrantLock公平锁和非公平锁的实现_第1张图片

公平锁源码

protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
	// 获取锁状态
    int c = getState(); 
    // 如果当前没有线程获取锁,
    if (c == 0) {
        // !hasQueuedPredecessors()保证线程都按顺序使用锁
        // 判断当前线程是否为等待队列中的头结点
        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;
}

公平锁中能够保证公平的就是这个方法 hasQueuedPredecessors() 来保证线程都按顺序使用锁
就是来判断当前线程是否处于队列中的头结点,如果不是头结点那么就需要排队,如果是头结点就去尝试获取锁

    public final boolean hasQueuedPredecessors() {
        // The correctness of this depends on head being initialized
        // before tail and on head.next being accurate if the current
        // thread is first in queue.
        Node t = tail; // Read fields in reverse initialization order
        Node h = head;
        Node s;
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
    }

我整理的流程图如下
[java 并发] ReentrantLock公平锁和非公平锁的实现_第2张图片

你可能感兴趣的:(java并发)