显式锁Lock
锁是用来控制多个线程访问共享资源的方式,在Lock接口出现之前,Java程序用我们所熟知的synchronized关键字来实现锁功能。synchronized是隐式锁,而Lock接口则是显式锁,隐式锁与显式锁的区别简单来说就是需不需要手动写代码去释放锁,需要的话就是显式锁,不需要的话就是隐式锁。
//隐式锁
synchronized(锁对象){
//任务代码
}
//显示锁
Lock l = new ReentrantLock()
@Override
public void run(){
l.lock;
//任务代码
try{
}finaly{
l.unlock;
}
}
Lock接口虽然少了隐式获取和释放锁的便利性,但是却拥有了锁获取和释放的可操作性、可中断的获取锁和超时获取锁等多种synchronized关键字所不具备的同步性能。
我们举例一个场景,使用手动操作显式获取和释放锁:先获取到了锁A,然后再去获取锁B,当锁B获取到了就释放锁A,再去获取锁C,当C获取到了同时释放锁B和去获取锁D。显然隐式锁做不到这点
Lock的使用很简单,如下
Lock lock = new ReentrantLock();
lock.lock();
try {
//你的业务代码
}finally {
lock.unlock();
}
在finally块中释放锁,目的就是保证获取到锁之后,最终能够被释放,记住不要将释放锁放在try代码块中,因为如果发生异常,try代码块中的释放锁可能不会被执行,导致锁得不到释放。
此外,Lock锁还具备synchronized关键字所不具备的主要特性,如下
- 尝试非阻塞地获取锁 : 当前线程尝试获取锁,当锁获得后,从该方法返回
- 能够被中断地获取锁:可中断地获取锁,和lock()方法的不同之处在于该方法会响应中断,即在锁的获取中可以中断当前线程。
- 超时获取锁:在指定的截止时间获取锁,如果截止时间到了仍旧无法获取锁,则返回。