今天看并发的时候,看的调用**wait()
方法会释放了锁,释放的是对象锁。**
有人现在就要问了,啥是对象锁,其实就是对象作为锁的条件。
final Object lock = new Object();
synchronized (lock){
//同步代码块
}
上述就是一个对象锁。
wait()方法是否会自动释放锁?
继续看,然后我就去做了一个小测试,看看调用wait方法,会不会释放对象锁。
这里让线程1拿到对象锁,再开始休眠;再让线程2去拿对象锁。
如果线程2拿到对象锁,代表wait方法会自动释放所拿到的对象锁。
final Object lock = new Object();
String resource = "resource";
new Thread(()->{
while (true){
synchronized (lock){
System.out.println(Thread.currentThread().getName()+"获取到对象锁");
try {
lock.wait();
System.out.println(Thread.currentThread().getName() + "开始沉睡");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
try {
Thread.sleep(3000); //休眠3s
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}).start();
new Thread(()->{
while (true){
synchronized (lock){
System.out.println(Thread.currentThread().getName()+"唤醒所以锁");
lock.notifyAll();
}
try {
Thread.sleep(3000); //休眠3s
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}).start();
运行结果如下:还真会自动释放锁。

问题提出,会不会释放在wait方法之外的所有锁呢?
使用wait()方法会不会释放拿到的所有锁?
所以我让线程1先去拿到资源,再去拿对象锁,然后再休眠,看看线程2是否能拿到资源,如果拿到代表wait方法可以释放所有拿到的锁;如果没拿到,代表只能释放当前拿到的对象锁。
final Object lock = new Object();
String resource = "resource";
new Thread(() -> {
while (true) {
synchronized (resource){
System.out.println(Thread.currentThread().getName() +"获取到了资源");
synchronized (lock){
lock.notify();
System.out.println(Thread.currentThread().getName() +"去唤醒任意线程");
System.out.println(Thread.currentThread().getName() + "获取对象锁");
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName()+"开始沉睡");
}
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println();
}
}, "线程 1").start();
new Thread(() -> {
while (true) {
synchronized (resource){
System.out.println(Thread.currentThread().getName() +"获取到资源");
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println();
}
}, "线程 2").start();
结果如下:wait方法并不能释放拿到的所有锁,只会释放拿到的当前的对象锁。

好吧,这只是一个无聊的测试。。。。。主要是问GPT时候,它告诉了我错误答案,所以才测试了。
通过上述案例,我们再思考一个问题,
为什么wait方法不放在Thread类中,为什么放在Object类中?
wait()
是让获得对象锁的线程实现等待,会自动释放当前线程占有的对象锁。每个对象(Object
)都拥有对象锁,既然要释放当前线程占有的对象锁并让其进入 WAITING 状态,自然是要操作对应的对象(Object
)而非当前的线程(Thread
)。
类似问题如下:
为什么 sleep()
方法定义在 Thread
中
因为 sleep()
是让当前线程暂停执行,不涉及到对象类,也不需要获得对象锁。