快捷搜索: 王者荣耀 脱发

何谓公平锁与非公平锁

公平锁:多个线程按照申请锁的顺序去获得锁,线程会直接进入队列去排队,永远都是队列的第一位才能得到锁 非公平锁:多个线程去获取锁的时候,会直接去尝试获取,获取不到,再去进入等待队列,如果能获取到,就直接获取到锁。

锁 优点 缺点 公平锁 所有线程都会获得锁,不会饿死 要唤醒阻塞的线程,CPU唤醒线程开销大 吞吐量下降 – – – 不公平锁 减少CPU唤醒线程的开销 吞吐效率较高 多个线程竞争,可能由于抢不到锁导致饿死

在ReentrantLock章节,其实涉及到了公平锁与非公平锁,下面我们来回顾一下

我们平时new 的ReentrantLock的时候,它的底层就使用了公平锁和非公平锁

public ReentrantLock() {
          
   
        sync = new NonfairSync();//默认是非公平锁
    }
public ReentrantLock(boolean fair) {
          
   
        sync = fair ? new FairSync() : new NonfairSync();
    }

细看公平锁与非公平锁的源码,发现都继承了ReentrantLock的内部类Sync,而Sync继承AQS(AbstractQueuedSynchronizer) 公平锁与非公平锁的主要的处理逻辑在tryAcquire方法上,而唯一的不同就在于公平锁多了一个hasQueuedPredecessors方法的判断 。

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

进入hasQueuedPredecessors方法,看看是怎么一回事

public final boolean hasQueuedPredecessors() {
          
   
        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());
    }

大概意思就是判断当前线程是否是在同步队列的头部,是返回true,不是返回false 因为公平锁是同步队列的首部才可以获取锁,所以才多了一个判断,非公平锁不需要

经验分享 程序员 微信小程序 职场和发展