锁超时原理介绍
ReentrantLock支持设置锁等待超时时间,即在一定时间内未获得锁的线程可以选择放弃等待,避免死锁
通过查看tryLock()实现方法 发现加锁的逻辑在doAcquireNanos中实现的,它接受两个参数:arg
表示获取锁时的参数,nanosTimeout
表示最大等待时间(以纳秒为单位)。
这个方法具体逻辑如下:
-
首先,线程会尝试获取锁。如果锁当前未被其他线程持有,则线程直接获取锁并返回true。
-
如果锁被其他线程持有,线程将进入等待队列,并启动一个计时器,设置超时时间。
-
在等待过程中,线程可能会被其他线程中断,或者等待时间达到设定的超时时间。如果发生这些情况,线程将停止等待,并返回false。
-
如果线程在超时时间内成功获取了锁,则停止计时器,并返回true。
代码测试
先看没有设置超时时间的情况
import java.util.concurrent.locks.ReentrantLock;
import static java.lang.Thread.sleep;
public class Test02 {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Thread t1 = new Thread(() -> {
System.out.println("線程1開始執行");
if(!lock.tryLock()){
System.out.println("線程1獲取鎖失敗");
return;
}
try {
System.out.println("線程1獲得了鎖");
}finally {
lock.unlock();
}
},"t1");
lock.lock();
System.out.println("主線程獲得了鎖");
t1.start();
try {
sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
执行结果如下:
加上超时时间:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import static java.lang.Thread.sleep;
public class Test01 {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
System.out.println("尝试获得锁");
try {
if (!lock.tryLock(2, TimeUnit.SECONDS)) {
System.out.println("获取不到锁");
return;
}
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("获取不到锁");
return;
}
try {
System.out.println("获得到锁");
} finally {
lock.unlock();
}
}, "t1");
lock.lock();
System.out.println("获得到锁");
t1.start();
sleep(1);
System.out.println("释放了锁");
lock.unlock();
}
}
执行结果如下: