10 公平锁和非公平锁

vvEcho 2025-03-01 14:09:00
Categories: Tags:

Java中提供的synchronized只能是非公平锁。

Java中提供的ReentrantLock,ReentrantReadWriteLock可以实现公平锁和非公平锁

公平锁

公平锁,先到先得;多个线程按顺序排队获取锁,每个线程获取机会均等,但永远只有队列首位线程能获取到锁。

优点:每个线程等待一段时间后,都有执行的机会,不至于出现某个线程饿死在队列中。
缺点:是队列里面除了第一个线程,其他的线程都会阻塞,cpu 唤醒阻塞线程的开销会很大

非公平锁

多个线程(不管是不是队列首位)去获取锁时会尝试直接获取锁,能获取到就执行任务,否则乖乖排队。代表实现是CAS比较并交换;

优点:获取锁更加灵活、吞吐量大、减少CPU唤醒线程的开销。
缺点:会出现某些线程永远获取不到锁,饿死在队列中,最终由 JVM 回收

注意锁的获取有三个条件:看状态state是否是0,当前线程是否为null; 是否排在队首
公平锁跟非公平锁加锁的逻辑差不多,唯一就是公平加锁的 if 判断中多了 hasQueuedPredecessors 是否队首

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;
}

推荐博客:公平锁和非公平锁