Java中提供的synchronized只能是非公平锁。
Java中提供的ReentrantLock,ReentrantReadWriteLock可以实现公平锁和非公平锁
公平锁
公平锁,先到先得;多个线程按顺序排队获取锁,每个线程获取机会均等,但永远只有队列首位线程能获取到锁。
优点:每个线程等待一段时间后,都有执行的机会,不至于出现某个线程饿死在队列中。
缺点:是队列里面除了第一个线程,其他的线程都会阻塞,cpu 唤醒阻塞线程的开销会很大
非公平锁
多个线程(不管是不是队列首位)去获取锁时会尝试直接获取锁,能获取到就执行任务,否则乖乖排队。代表实现是CAS比较并交换;
优点:获取锁更加灵活、吞吐量大、减少CPU唤醒线程的开销。
缺点:会出现某些线程永远获取不到锁,饿死在队列中,最终由 JVM 回收
注意锁的获取有三个条件:看状态state是否是0,当前线程是否为null; 是否排在队首
公平锁跟非公平锁加锁的逻辑差不多,唯一就是公平加锁的 if 判断中多了 hasQueuedPredecessors 是否队首
1 | protected final boolean tryAcquire(int acquires) { |
推荐博客:公平锁和非公平锁