在Cracking the Coding Interview的Threads and Locks章节中(第6版为15,第5版为16),以下是问题5:
按顺序调用: 假设我们有以下代码:
public class Foo {
public Foo() { ... }
public void first() { ... }
public void second() { ... }
public void third() { ... }
}
Foo的同一个实例将传递给三个不同的线程。 threadA
会致电first()
,threadB
会致电second()
,threadC
会致电third()
。设计一种机制,确保在first
之前调用second
并在second
之前调用third
。
我的理解是建议的解决方案使用以下过程:
sem1
和sem2
。first()
中,运行程序,然后在返回之前立即释放(增量)sem1
。second()
中,等待获取sem1
,然后在运行此过程之前将其释放。发布sem2
。third()
中,等待获取sem2
,发布sem2
,然后运行此过程。这或多或少是我所做的。然而,该解决方案还声称,“因为我们需要非常小心线程安全性,简单的布尔标志将无法完成工作。”
简单地保留两个(最初为假的)布尔标志firstDone
和secondDone
并在相应方法的末尾将它们设置为true会产生什么正确性问题? second()
和third()
只会分别在firstDone
和secondDone
上旋转。
我现在已经考虑过这个问题超过一个小时了,而且我没有看到这个策略的(与性能无关的)问题。实际上,如果我们将false
视为整数0并将true
视为1,则两者看起来几乎完全相同,因为布尔值始终与给定信号量的值相匹配在代码中指出。