@Test
public void test() {
try {
new Object().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
但是,为毛呢??为毛呢?我也不知道啊,经过一番查阅,我找到了答案。
Lost Wake-Up Problem
事情得从一个多线程编程里面臭名昭著的问题"Lost wake-up problem"说起。
这个问题并不是说只在Java语言中会出现,而是会在所有的多线程环境下出现。
假如我们有两个线程,一个消费者线程,一个生产者线程。生产者线程的任务可以简化成先将count加一,而后唤醒消费者;消费者则是先将count减一,而后在减到0的时候陷入睡眠:
生产者伪代码:
count+1;
notify();
消费者伪代码:
while(count<=0)
wait()
count–
这里面有问题。什么问题呢?
生产者是两个步骤:
- count+1;
- notify();
消费者也是两个步骤:
- 检查count值;
- 睡眠或者减一;
如果这些步骤混在一起会怎样呢?
比如说,初始的时候count等于0,这个时候消费者检查count的值,发现count小于等于0的条件成立;就在这个时候,发生了上下文切换,生产者进来了,噼噼啪啪一顿操作,把两个步骤都执行完了,也就是发出了通知,准备唤醒一个线程。这个时候消费者刚决定睡觉,还没睡呢,所以这个通知就会被丢掉。紧接着,消费者就睡过去了,消费者成睡美人了。
这就是所谓的lost wake up问题。
尝试解决
问题的根源在于,消费者在检查count到调用wait()之间,count就可能被改掉了。
常见的解决方式是加锁,让消费者和生产者竞争一把锁,竞争到了的,才能够修改count的值。
我这里将两者的两个操作都放进去了同步块中,于是生产者的代码是:
tryLock()
count+1
notify()
releaseLock()
消费者的代码是:
tryLock()
while(count <= 0)
wait()
count-1
releaseLock()
但是这样改后依旧会出现lost wake up问题,而且和无锁的表现是一样的。
最终解决
为了避免出现这种lost wake up问题,在这种模型之下,应该将我们的代码放进去的同步块中。
最后希望可以帮助到大家!
千千万万要记得:多刷题!!多刷题!!
之前算法是我的硬伤,后面硬啃了好长一段时间才补回来,算法才是程序员的灵魂!!!!
篇幅有限,以下只能截图分享部分的资源!!
(1)多线程(这里以多线程为代表,其实整理了一本JAVA核心架构笔记集)
(2)刷的算法题(还有左神的算法笔记)
(3)面经+真题解析+对应的相关笔记(很全面)
(4)视频学习(部分)
ps:当你觉得学不进或者累了的时候,视频是个不错的选择
在这里,最后只一句话:祝大家offer拿到手软!!
[外链图片转存中…(img-04D9jftU-1714334082209)]
(4)视频学习(部分)
ps:当你觉得学不进或者累了的时候,视频是个不错的选择
在这里,最后只一句话:祝大家offer拿到手软!!