![]() |
1
109
这是一个非常简单的Java活灵活现的例子,丈夫和妻子在尝试喝汤,但是他们之间只有一个勺子。夫妻双方都太客气了,如果对方还没吃东西,他们会把勺子递给对方。
|
![]() |
2
71
撇开轻率的注释不谈,我们知道出现的一个例子是代码,它试图检测和处理死锁情况。如果两个线程检测到一个死锁,并试图为对方“让开”,而不加注意,它们最终将陷入一个始终“让开”且永远无法向前移动的循环中。 我说的“让开”是指他们会释放锁,并试图让另一个获得它。我们可以想象两个线程这样做的情况(伪代码):
撇开竞争条件不谈,我们这里的情况是,如果两个线程同时进入,那么它们最终将在内部循环中运行而不继续。显然这是一个简单的例子。一个简单的解决方法是在线程等待的时间内加入某种随机性。 正确的解决方法是始终尊重 lock heirarchy . 选择一个你获得锁的顺序并坚持下去。例如,如果两个线程总是在lock2之前获取lock1,则不可能出现死锁。 |
![]() |
3
6
由于没有被标记为接受答案的答案,我尝试创建实时锁示例; Original program 我是在APR 2012编写的,学习了多线程的各种概念。这次我修改了它以创建死锁、竞争条件、livelock等。 所以让我们先理解问题陈述; Cookie Maker问题 有一些配料容器: 巧克力容器 , 小麦粉容器 . 厨具匠 从配料容器中取出一些粉末来烘烤 曲奇饼干 . 如果cookie生成器发现一个容器为空,它会检查另一个容器以节省时间。一直等到 填料 填充所需的容器。有一个 填料 他定期检查集装箱,如果集装箱需要,他会装一些。 请检查上的完整代码 github ; 让我简单地解释一下你的实现。
让我们看看代码: 厨师.java
ingredientcontainer.java
一切顺利,直到 填料 正在装满容器。但如果我忘记启动填充程序,或者填充程序意外离开,子线程会不断更改其状态,以允许其他制造商去检查容器。 我还创建了一个守护进程 ThreadTracer 它监视线程状态和死锁。这是控制台的输出;
你会注意到子线程并改变它们的状态和等待。 |
![]() |
4
4
一个真实的(尽管没有确切的代码)示例是两个相互竞争的进程实时锁定,试图纠正SQL Server死锁,每个进程使用相同的等待重试算法重试。虽然这是计时的幸运,但我已经看到在具有类似性能特征的单独计算机上发生这种情况,以响应添加到ems主题的消息(例如,多次保存单个对象图的更新),并且无法控制锁顺序。 很好的解决办法 这 这样的情况就是要有相互竞争的消费者(通过将工作划分到不相关的对象上,尽可能防止重复处理在链的最高层)。 一个不太理想的(好的,肮脏的黑客)解决方案是提前打破计时坏运气(处理中的一种强制差异),或者在死锁后使用不同的算法或一些随机因素来打破它。这仍然可能有问题,因为对于每个进程来说,可能的锁获取顺序是“粘性的”,这需要一定的最短时间,而等待重试中没有考虑到这一点。 另一个解决方案(至少对于sql server)是尝试不同的隔离级别(例如快照)。 |
![]() |
5
2
我把两个人在走廊里经过的例子编成代码。一旦意识到方向相同,这两条线就会相互避开。
|
|
6
2
杰伯恩代码的C版:
|
![]() |
7
1
这里的一个例子可能是使用定时锁来获得一个以上的锁,如果你不能全部获得,请退回并再试一次。
我可以想象这样的代码会有问题,因为有很多线程冲突并等待获取一组锁。但作为一个简单的例子,我不确定这是否很有说服力。 |
![]() |
8
0
jelbourn代码的python版本:
|
|
9
0
我修改了@jelbourn的答案。 当他们中的一个发现另一个饿了,他(她)应该释放勺子并等待另一个通知,这样就发生了活锁。
|
![]() |
10
0
|
![]() |
a a · 为什么在这个可重入锁示例中需要引用计数? 2 年前 |
![]() |
Grant · goroutines有高空闲唤醒电话 2 年前 |
![]() |
hoaz · 如何安全地清理并发映射 6 年前 |
![]() |
Alanpatchi · int基元类型的volatile声明 6 年前 |