公平锁和非公平锁的区别?
典型回答 非公平锁:多个线程不按照申请锁的顺序去获得锁,而是直接去尝试获取锁,获取不到,再进入队列等待,如果能获取到,就直接获取到锁。 公平锁:多个线程按照申请锁的顺序去获得锁,所有线程都在队列里排队,这样就保证了队列中的第一个先得到锁。 两种锁分别适合不同的场景中,存在着各自的优缺点,对于公平锁来说,他的优点是所有的线程都能得到资源,不会饿死在队列中。但是他存在着吞吐量会下降很多,队列里面除了第一个线程,其他的线程都会阻塞,cpu唤醒阻塞线程的开销会很大的缺点。 而对于非公平锁来说,他可以减少CPU唤醒线程的开销,整体的吞吐效率会高点,CPU也不必去唤醒所有线程,会减少唤起线程的数量。但是他可能会导致队列中排队的线程一直获取不到锁或者长时间获取不到锁,活活饿死的情况。 扩展知识 ReentrantLock 分为公平锁和非公平锁,可以通过构造方法来指定具体类型: 1 2 3 4 //默认非公平锁 public ReentrantLock() { sync = new NonfairSync(); } 1 2 3 4 //公平锁 public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } 默认一般使用非公平锁,它的效率和吞吐量都比公平锁高的多。 reentrantLock的非公平锁实现 非公平锁的lock的核心逻辑在NonfairSync中,具体代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 /** * Sync object for non-fair locks */ static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** * Performs lock. Try immediate barge, backing up to normal * acquire on failure. */ final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } } ...