之前有面试官问过是否可以在子线程中获取父线程所持有的锁,我根据以前看过的 ReentrantLock 的源码分析, AQS 的队首节点中保存的是成功获取同步状态 state 的线程引用,与父子线程无关,所以是不可以的
今天来实际的测试一下
1. ReentrantLock 测试
/**
* Author: heatdeath
* Date: 2018/7/15
* Desc:
*/
public class GetLockInChildThreadDemo {
private static Lock lock = new ReentrantLock();
public static void main(String[] args) {
lock.lock();
try {
System.out.println(Thread.currentThread() + " i got the lock");
new Thread(() -> {
lock.lock();
try {
System.out.println(Thread.currentThread() + " I got the lock and going to sleep");
Thread.sleep(5000);
System.out.println(Thread.currentThread() + " I am waked up");
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
lock.unlock();
}
}).start();
Thread.sleep(6000);
System.out.println(Thread.currentThread() + " I am waked up");
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
lock.unlock();
}
}
}
输出
Thread[main,5,main] i got the lock
Thread[main,5,main] I am waked up
Thread[Thread-0,5,main] I got the lock and going to sleep
Thread[Thread-0,5,main] I am waked up
2. synchronized 测试
/**
* Author: heatdeath
* Date: 2018/7/15
* Desc:
*/
public class GetLockInChildThreadDemo {
public static void main(String[] args) {
synchronized (GetLockInChildThreadDemo.class) {
try {
System.out.println(Thread.currentThread() + " i got the lock");
new Thread(() -> {
synchronized (GetLockInChildThreadDemo.class) {
try {
System.out.println(Thread.currentThread() + " I got the lock and going to sleep");
Thread.sleep(5000);
System.out.println(Thread.currentThread() + " I am waked up");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}).start();
Thread.sleep(6000);
System.out.println(Thread.currentThread() + " I am waked up");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
输出:
Thread[main,5,main] i got the lock
Thread[main,5,main] I am waked up
Thread[Thread-0,5,main] I got the lock and going to sleep
Thread[Thread-0,5,main] I am waked up
GetLockInChildThreadDemo.class 对象只有一个 moniter ,只有等待 main 线程执行到 moniterexit 指令时,子线程才能执行 moniterenter 获取锁