与 synchronized的异同点:
相同:都支持可重入
可重入:可重入是指同一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁 如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡住
@Slf4j(topic = "c.TestReentrant")
public class TestReentrant {
static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
method1();
}
public static void method1() {
lock.lock();
try {
log.debug("execute method1");
method2();
} finally {
lock.unlock();
}
}
public static void method2() {
lock.lock();
try {
log.debug("execute method2");
method3();
} finally {
lock.unlock();
}
}
public static void method3() {
lock.lock();
try {
log.debug("execute method3");
} finally {
lock.unlock();
}
}
}
不同:对于 synchronized它具备如下特点
可中断
两个线程同时去争一把锁的情况下,可以避免让没获取到的一直处于等待状态
lockInterruptibly()
demo如下:
package concurrent.reentrantlock;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.ReentrantLock;
import static util.Sleeper.sleep;
@Slf4j(topic = "c.TestInterrupt")
public class TestInterrupt {
public static void main(String[] args) {
test2();
}
private static void test2() {
ReentrantLock lock = new ReentrantLock();
Thread t1 = new Thread(() -> {
log.debug("启动...");
lock.lock();
try {
log.debug("获得了锁");
} finally {
lock.unlock();
}
}, "t1");
lock.lock();
log.debug("获得了锁");
t1.start();
try {
sleep(1);
t1.interrupt();
log.debug("执行打断");
sleep(1);
} finally {
log.debug("释放了锁");
lock.unlock();
}
}
private static void test1() {
ReentrantLock lock = new ReentrantLock();
Thread t1 = new Thread(() -> {
log.debug("启动...");
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
e.printStackTrace();
log.debug("等锁的过程中被打断");
return;
}
try {
log.debug("获得了锁");
} finally {
lock.unlock();
}
}, "t1");
lock.lock();
log.debug("main 获得了锁");
t1.start();
try {
sleep(1);
t1.interrupt();
log.debug("main 执行打断");
} finally {
lock.unlock();
}
}
}
可以设置超时时间
tryLock(1, TimeUnit.SECONDS)
package concurrent.reentrantlock;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.ReentrantLock;
import static util.Sleeper.sleep;
@Slf4j(topic = "c.TestInterrupt")
public class TestInterrupt {
public static void main(String[] args) {
test1();
}
private static void test2() {
ReentrantLock lock = new ReentrantLock();
Thread t1 = new Thread(() -> {
log.debug("t1 启动...等锁中");
lock.lock();
try {
log.debug("获得了锁");
} finally {
lock.unlock();
}
}, "t1");
lock.lock();
log.debug("获得了锁");
t1.start();
try {
sleep(1);
t1.interrupt();
log.debug("执行打断");
sleep(1);
} finally {
log.debug("释放了锁");
lock.unlock();
}
}
private static void test1() {
ReentrantLock lock = new ReentrantLock();
Thread t1 = new Thread(() -> {
log.debug("启动...");
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
e.printStackTrace();
log.debug("等锁的过程中被打断");
return;
}
try {
log.debug("获得了锁");
} finally {
lock.unlock();
}
}, "t1");
lock.lock();
log.debug("main 获得了锁");
t1.start();
try {
sleep(1);
t1.interrupt();
log.debug("main 执行打断");
} finally {
lock.unlock();
}
}
}
可以设置为公平锁
公平锁一般没有必要,会降低并发度;可以使用tryLock()去设置超时时间。
支持多个条件变量
送烟、送外卖的例子;
多个条件变量,对应多个等待区;