持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情
基本介绍
RennttrantLock也是锁和synchronized一样具有锁定同步代码块的作用,不过和synchronized还是有很多不一样的地方。 RennttrantLock是java.util.concurrent(juc) 下的一个类,相对于synchronized它具备如下特点:
- 可以打断处于BLOCKED状态的其他线程
- 可以设置处于BLOCKED状态的线程超时时间,如果超过这个时间就放弃争抢锁
- 可以设置为公平锁,线程按照先入先出获取锁
- 支持多个条件变量,这个是指 对于等待区 我们可以由多个 不同对象调用锁处于等待状态时所在的等待区不同,对于synchronized锁来说 它的等待区就只有一个WaitSet
与synchronized一样 都支持锁重入,即自己可以再次获取自己内部的锁
基本语法
ReentrantLock lock = new ReentrantLock();
lock.lock();
try{
// lock.lock();
// 临界区
}finally{
// 释放锁
lock.unlock();
}
注意:lock.lock();可以放在try外面,也可以放在try里面,最后在finally中需要进行lock.unlock();释放锁
可锁重入
代码示例
public class TestInterKCR {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
lock.lock();
try {
System.out.println("enter main");
m1();
}finally {
lock.unlock();
}
}
private static void m1(){
lock.lock();
try {
System.out.println("enter m1");
m2();
}finally {
lock.unlock();
}
}
private static void m2(){
lock.lock();
try {
System.out.println("enter m2");
}finally {
lock.unlock();
}
}
}
结果:
enter main
enter m1
enter m2
解释:
可以看出自己内部的锁都可以调用,没有发生死锁,说明可以锁重入
可打断
我们先要明确一个概念,这里说的可打断 说的是 一个已经获得锁的线程t1 和一个处于阻塞状态线程的t2(因为t1已经获取了锁),我们可以在其他线程中 把 t2线程打断 使之 跳出阻塞状态 运行其它部分代码。
那么为什么 synchronized不可以被打断?
代码示例
public class TestInterSync {
private static String a = "s";
public static void main(String[] args) {
Thread t1 = new Thread(()->{
System.out.println("t1尝试获取锁");
synchronized (a){
System.out.println("t1获取到锁");
boolean interrupted = Thread.currentThread().isInterrupted();
if (interrupted){
System.out.println("t1被打断");
}
}
});
Thread t2 = new Thread(()->{
System.out.println("t2尝试获取锁");
synchronized (a){
System.out.println("t2获取到锁");
while (true){
}
}
});
t2.start();
Sleeper.sleep(0.5);
t1.start();
Sleeper.sleep(0.5);
System.out.println("打断正在等待锁的t1线程");
t1.interrupt();
}
}
结果:
程序没有结束:
t2尝试获取锁
t2获取到锁
t1尝试获取锁
打断正在等待锁的t1线程
解释:
我们发现程序并没有结束,我们的t2线程先获取到锁且没有释放锁,导致t1线程阻塞,现在我们在主线程中打断t1线程 但是发现无法打断
lOC可以被打断吗?
代码示例
public class TestInterReenY {
private static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread(()->{
System.out.println("t1尝试获取锁");
lock.lock();
try {
System.out.println("t1获取到锁");
}finally {
lock.unlock();
}
});
Thread t2 = new Thread(()->{
System.out.println("t2尝试获取锁");
lock.lock();
try {
System.out.println("t2获取到锁");
Sleeper.sleep(2);
}finally {
}
});
t2.start();
Sleeper.sleep(0.5);
t1.start();
Sleeper.sleep(0.5);
System.out.println("打断正在等待锁的t1线程");
t1.interrupt();
}
}
结果:
程序没有结束:
t2尝试获取锁
t2获取到锁
t1尝试获取锁
打断正在等待锁的t1线程
解释:
我们发现lock方法依然不能打断处于阻塞状态的线程,那我们应该用什么,答案是lockInterruptibly方法