ReentrantLock は Lock インターフェイスを実装し、Lock クラスのメソッドを書き換えます。次の特性があります
1. リエントラント。つまり、同じロック オブジェクトを同じスレッド内で繰り返しロックできます。
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();
}
}
}
2. 中断可能。lock.lockInterruptibly() メソッドを使用します。
3. ロックのタイムアウト。lock.tryLock() メソッドを使用します。
public class TestTimeout {
public static void main(String[] args) {
test1();
}
private static void test1() {
ReentrantLock lock = new ReentrantLock();
Thread t1 = new Thread(() -> {
log.debug("启动...");
try {
if (!lock.tryLock(1, TimeUnit.SECONDS)) {
log.debug("获取等待 1s 后失败,返回");
return;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
log.debug("获得了锁");
} finally {
lock.unlock();
}
}, "t1");
lock.lock();
log.debug("获得了锁");
t1.start();
try {
sleep(2);
} finally {
lock.unlock();
}
}
}
4. 公平・不公平を設定可能。直接コンストラクターは ReentrantLock(boolean Fair) を渡します。
5. 複数の条件を設定できます。await、signal を使用して通信します。
public class ReentreantLock01 {
private static Lock lock = new ReentrantLock();
static Condition condition1 = lock.newCondition();
static Condition condition2 = lock.newCondition();
private static boolean flag1 = false;
private static boolean flag2 = false;
public static void main(String[] args) {
new Thread(()->{
try {
lock.lock();
log.info("开始干活");
while (!flag1){
try {
log.info("进入休息1");
condition1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (!flag1){
log.info("暂时干不了活");
}else {
log.info("可以干活");
}
}finally {
lock.unlock();
}
},"t1").start();
new Thread(()->{
try {
lock.lock();
log.info("开始干活2");
while (!flag2){
try {
log.info("进入休息2");
condition2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (!flag2){
log.info("暂时干不了活2");
}else {
log.info("可以干活2");
}
}finally {
lock.unlock();
}
},"t2").start();
SleepUtils.sleep(5);
try {
if (lock.tryLock()) {
log.info("主线程获取锁成功");
flag1 = true;
condition1.signal();
SleepUtils.sleep(5);
flag2 = true;
condition2.signal();
}
}finally {
lock.unlock();
}
}