1. ReentrantLock
1.1 ReentrantLock VS. synchronized
-
ReentrantLock
相比synchronized
而言功能更加丰富,使用起来更为灵活,也更适合复杂的并发场景 - 都是独占锁
- 都是可重入的,
synchronized
因此可以放在递归中,而重入锁需要保证加锁和解锁次数一样
1.2 创建公平锁
// 传入true 创建公平锁
ReentrantLock lock = new ReentrantLock(true);
参考资料:ReentrantLock(重入锁)功能详解和应用演示
1.3 响应中断
-
lockInterruptibly()
:可以响应中断的取锁方法 -
Thread#interrupt()
:线程中断
public class ReentrantLockTest {
static Lock lock1 = new ReentrantLock();
static Lock lock2 = new ReentrantLock();
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new ThreadDemo(lock1, lock2));//该线程先获取锁1,再获取锁2
Thread thread1 = new Thread(new ThreadDemo(lock2, lock1));//该线程先获取锁2,再获取锁1
thread.start();
thread1.start();
thread.interrupt();//是第一个线程中断
}
static class ThreadDemo implements Runnable {
Lock firstLock;
Lock secondLock;
public ThreadDemo(Lock firstLock, Lock secondLock) {
this.firstLock = firstLock;
this.secondLock = secondLock;
}
@Override
public void run() {
try {
firstLock.lockInterruptibly();
TimeUnit.MILLISECONDS.sleep(10);//更好的触发死锁
secondLock.lockInterruptibly();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
firstLock.unlock();
secondLock.unlock();
System.out.println(Thread.currentThread().getName()+"正常结束!");
}
}
}
}
1.4 获取锁时限时等待
-
ReentrantLock#tryLock()
:可以选择传入时间参数,表示等待指定的时间,无参则表示立即返回锁申请的结果:true
表示获取锁成功,false
表示获取锁失败 - 可以用来解决死锁问题
2. 公平锁/非公平锁
公平锁:在锁可用时,在锁上等待时间最长的线程获得锁
非公平锁:随机分配这种使用权
-
公平锁就是在获取锁之前会先用
hasQueuedPredecessors
判断等待队列是否为空或者自己是否位于队列头部,该条件通过才能继续获取锁。 - 非公平锁比公平锁性能更好,公平锁能够防止饥饿
参考资料:一张图读懂非公平锁与公平锁