公平锁和非公平锁区别
- 公平锁:大家老老实实排队,先来后到,等待队列按照FIFO规则获取锁。
- 非公平锁:抢占资源,多线程获取锁的顺序不按照申请锁的顺序;在高并发情况下,有可能会造成优先级反转或饥饿现象;优点在于性能比公平锁大。
如何得到公平/非公平锁?
并发包中ReentrantLock的创建可以指定构造函数的boolean类型来得到公平/非公平锁,默认是非公平锁。
ReentrantLock默认是非公平锁;synchronized也是非公平锁。
可重入锁(又名递归锁)
可重入锁,也叫做递归锁,指的是同一线程外层函数获得锁之后,内层递归函数仍然能获取该锁的代码,在同一线程在外层方法获取锁的时候,在进入内层方法会自动获取锁,也就是说线程可以进入任何一个他已经拥有的锁所同步着的代码块;当一个线程请求得到一个对象锁后再次请求此对象锁,可以再次得到该对象锁。
ReentrantLock内部只有一个成员变量Sync,作为一个核心内部类,绝大部分方法都直接依赖这个类实现。
Sync是AQS[AbstractQueuedSynchronizer]的抽象子类
ReentrantLock和sync是典型的可重入锁;ReentrantLock在重入时要却确保重复获取锁的次数必须和重复释放锁的次数一样,否则可能导致其他线程无法获得该锁。
可重入锁的最大作用是避免死锁。
Lock lock = new ReentrantLock();
public void get() {
lock.lock();
System.out.println(Thread.currentThread().getId());
set();
lock.unlock();
}
public void set() {
lock.lock();
System.out.println(Thread.currentThread().getId());
lock.unlock();
}
调用 get() 方法,同一个线程 ID 会被连续输出两次。