当前位置:网站首页>漫画:怎么证明sleep不释放锁,而wait释放锁?
漫画:怎么证明sleep不释放锁,而wait释放锁?
2022-08-03 12:28:00 【Java中文社群】







wait 加锁示例
public class WaitDemo {
private static Object locker = new Object();
public static void main(String[] args) throws InterruptedException {
WaitDemo waitDemo = new WaitDemo();
// 启动新线程,防止主线程被休眠
new Thread(() -> {
try {
waitDemo.doWait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
Thread.sleep(200); // 此行本身没有意义,是为了确保 wait() 先执行再执行 notify()
waitDemo.doNotify();
}
/**
* 执行 wait()
*/
private void doWait() throws InterruptedException {
synchronized (locker) {
System.out.println("wait start.");
locker.wait();
System.out.println("wait end.");
}
}
/**
* 执行 notify()
*/
private void doNotify() {
synchronized (locker) {
System.out.println("notify start.");
locker.notify();
System.out.println("notify end.");
}
}
}以上程序的执行结果为:
wait start.
notify start.
notify end.
wait end.
代码解析
从上述代码可以看出,我们给 wait() 和 notify() 两个方法上了同一把锁(locker),但在调用完 wait() 方法之后 locker 锁就被释放了,所以程序才能正常执行 notify() 的代码,因为是同一把锁,如果不释放锁的话,是不会执行 notify() 的代码的,这一点也可以从打印的结果中证实(结果输出顺序),所以综合以上情况来说 wait() 方法是释放锁的。
sleep 加锁示例
public class WaitDemo {
private static Object locker = new Object();
public static void main(String[] args) throws InterruptedException {
WaitDemo waitDemo = new WaitDemo();
// 启动新线程,防止主线程被休眠
new Thread(() -> {
synchronized (locker) {
try {
System.out.println("sleep start.");
Thread.sleep(1000);
System.out.println("sleep end.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(200);
waitDemo.doNotify();
}
/**
* 执行 notify()
*/
private void doNotify() {
synchronized (locker) {
System.out.println("notify start.");
locker.notify();
System.out.println("notify end.");
}
}
}以上程序的执行结果为:
sleep start.
sleep end.
notify start.
notify end.
代码解析
从上述代码可以看出 sleep(1000) 方法(行号:11)执行之后,调用 notify() 方法并没有获取到 locker 锁,从上述执行结果中可以看出,而是执行完 sleep(1000) 方法之后才执行的 notify() 方法,因此可以证明调用 sleep() 方法并不会释放锁。
知识扩展
1.sleep 和 wait 有什么区别?
sleep 和 wait 几乎是所有面试中必问的题,但想完全回答正确似乎没那么简单。
对于 sleep 和 wait 的区别,通常的回答是这样的:
wait 必须搭配 synchronize 一起使用,而 sleep 不需要;
进入 wait 状态的线程能够被 notify 和 notifyAll 线程唤醒,而 sleep 状态的线程不能被 notify 方法唤醒;
wait 通常有条件地执行,线程会一直处于 wait 状态,直到某个条件变为真,但是 sleep 仅仅让你的线程进入睡眠状态;
wait 方法会释放对象锁,但 sleep 方法不会。
但上面的回答显然遗漏了一个重要的区别,在调用 wait 方法之后,线程会变为 WATING 状态,而调用 sleep 方法之后,线程会变为 TIMED_WAITING 状态。
2.wait 能不能在 static 方法中使用?为什么?
不能,因为 wait 方法是实例方法(非 static 方法),因此不能在 static 中使用,源码如下:
public final void wait() throws InterruptedException {
wait(0);
}3.wait/notify 可以不搭配 synchronized 使用吗?为什么?
不行,因为不搭配 synchronized 使用的话程序会报错,如下图所示:
更深层次的原因是因为不加 synchronized 的话会造成 Lost Wake-Up Problem,唤醒丢失的问题,详情可见:https://juejin.im/post/5e6a4d8a6fb9a07cd80f36d1
总结
本文我们通过 synchronized 锁定同一对象,来测试 wait 和 sleep 方法,再通过执行结果的先后顺序证明:wait 方法会释放锁,而 sleep 方法并不会。同时我们还讲了几个 wait 和 sleep 的常见面试问题,希望本文可以帮助到你。

往期推荐
边栏推荐
- 秋招招工作
- 数据库系统原理与应用教程(076)—— MySQL 练习题:操作题 160-167(二十):综合练习
- 流式编程使用场景
- (through page) ali time to upload the jar
- [数据仓库]分层概念,ODS,DM,DWD,DWS,DIM的概念「建议收藏」
- 数据库系统原理与应用教程(075)—— MySQL 练习题:操作题 151-159(十九):综合练习
- 【Verilog】HDLBits题解——Verification: Writing Testbenches
- From the physical level of the device to the circuit level
- [Verilog] HDLBits Problem Solution - Circuits/Sequential Logic/Latches and Flip-Flops
- 信创建设看广州|海泰方圆亮相2022 信创生态融合发展论坛
猜你喜欢

利用ChangeStream实现Amazon DocumentDB表级别容灾复制

B站回应“HR 称核心用户都是 Loser”:该面试官去年底已被劝退,会吸取教训加强管理

海外代购系统/代购网站怎么搭建——源码解析

How to build an overseas purchasing system/purchasing website - source code analysis

论文理解:“Gradient-enhanced physics-informed neural networks for forwardand inverse PDE problems“

PC client automation testing practice based on Sikuli GUI image recognition framework

一次内存泄露排查小结

Feature dimensionality reduction study notes (pca and lda) (1)

别再用if-else了,分享一下我使用“策略模式”的项目经验...

YOLOv5 training data prompts No labels found, with_suffix is used, WARNING: Ignoring corrupted image and/or label appears during yolov5 training
随机推荐
fastposter v2.9.0 programmer must-have poster generator
[数据仓库]分层概念,ODS,DM,DWD,DWS,DIM的概念「建议收藏」
特征工程学习笔记
I in mother's womb SOLO20 years
Feature dimensionality reduction study notes (pca and lda) (1)
Simple implementation of a high-performance clone of Redis using .NET (1)
2022 年 CISO 最关心的是什么?
awk入门教程
为什么越来越多的开发者放弃使用Postman,而选择Eolink?
特征降维学习笔记(pca和lda)(1)
流式编程使用场景
链游NFT元宇宙游戏系统开发技术方案及源码
Knowledge Graph Question Answering System Based on League of Legends
博客记录生活
自律成就自己
Image fusion GAN-FM study notes
LyScript implements memory stack scanning
图像融合SDDGAN文章学习
第5章 实现首页Tab数据展示
海外代购系统/代购网站怎么搭建——源码解析


