我有以下问题需要解决:
考虑一个应用程序,其中有三种类型的线程:Calculus-A,Calculus-B和Finalization。每当线程类型Calculus-A结束时,它会调用例程endA(),它会立即返回。每当线程类型Calculus-B结束时,它会调用例程endB(),它会立即返回。 Finalization例程之类的线程调用wait(), 仅当它们已经完成两个Calculation-A线程和2个Calculation-B线程时才返回。换句话说,对于微积分-A的2个结论和微积分-B的2个结论,一个线程终结被允许继续。 3种类型的线程数量不确定。不知道线程调用的例程的顺序。线程完成按到达顺序回答。 使用信号量实现例程endA(),endB()和wait()。除了变量初始化之外,唯一可能的操作是P和V.不能接受繁忙等待的解决方案。
这是我的解决方案:
semaphore calcA = 2;
semaphore calcB = 2;
semaphore wait = -3;
void endA()
{
P(calcA);
V(wait);
}
void endB()
{
P(calcB);
V(wait);
}
void wait()
{
P(wait);
P(wait);
P(wait);
P(wait);
V(calcA);
V(calcA);
V(calcB);
V(calcB);
}
我相信由于等待初始化而导致死锁,if和wait()在endA()和endB()之前执行。还有其他解决办法吗?
答案 0 :(得分:4)
我倾向于将信号量问题视为必须识别“等待来源”的问题,并为每个信号量及其访问协议定义。
考虑到这一点,“等待的来源”是
CalcA和CalcB的完成因此应增加其各自的计数器。在另一端,一个终结线程获得对计数器的独占访问权,并以任何顺序等待所需的完成次数构成完成组。然后它会解锁对下一组的访问权限。
我的代码如下,但由于我不熟悉荷兰语V
和P
,我将使用take()
/ give()
。
semaphore calcA = 0;
semaphore calcB = 0;
semaphore groupSem = 1;
void endA(){
give(calcA);
}
void endB(){
give(calcB);
}
void wait(){
take(groupSem);
take(calcA);
take(calcA);
take(calcB);
take(calcB);
give(groupSem);
}
groupSem
信号量确保全有或全无:进入临界区的线程将获得每个CalcA和CalcB的下两个完成。如果不存在groupSem
,则输入wait
的第一个线程可能需要两个As并阻塞,然后由另一个抓取两个As和两个B然后逃跑的线程接管。
如果groupSem
不存在则存在一个更糟糕的问题,如果第二个线程采用两个As,一个B然后阻塞,然后第一个线程抓住第二个B.如果不知何故结果是finalization允许更多的CalculationA和CalculationB运行,然后你可能会遇到死锁,因为计算A和B的实例可能没有更多机会完成,因此最终化线程会挂起,无法生成更多的计算实例。