【发布时间】:2018-03-02 15:48:58
【问题描述】:
我有 10 个线程,每个线程都有自己的 ID,从 1 到 10;所有线程都有 2 个阶段要做(即 Phase1 和 Phase2)。我试图让所有线程首先完成它们的 Phase1,在任何线程进入 Phase2 之前,使用信号量(我做到了并且效果很好),但是我应该让所有 10 个线程按照它们的 TID(线程 ID)的顺序开始。 我尝试了很多方法,但没有得到结果!我得到的最终结果是只为前 4 个线程(有时是 5 或 6 个)工作,然后在其余线程中出现顺序混乱!
这些是我创建的信号量:
...private static Semaphore mutex = new Semaphore(1);
// s1 is to make sure phase I for all is done before any phase II begins
private static Semaphore s1 = new Semaphore(0);
// s2 is for use in conjunction with Thread.turnTestAndSet() for phase II proceed in the thread creation order
private static Semaphore s2 = new Semaphore(1);
private static int n=10;
private static int count = 0;
这是我的线程方法:
static class AcquireBlock extends BaseThread
{
public void run()
{
mutex.P();
phase1();
count++;
mutex.V();
if (count == n)
{
s1.V();
}
s1.P();
s1.V();
while(!this.turnTestAndSet());
s2.P();
phase2();
s2.V();
}
} // class AcquireBlock
turnTestAndSet方法如下:
public synchronized boolean turnTestAndSet()
{
if(siTurn == this.iTID)
{
siTurn++;
return true;
}
return false;
}
siTurn 初始化为 1。
我在代码中遇到的问题(我认为)是,当线程到达 While 循环 [while(!this.turnTestAndSet())] 时,它可能会成功跳过循环(在成功的情况下),但在前一个线程进入阶段 2 之前,另一个线程可能会启动并执行其 while 循环!因此,在任何线程进入阶段 2 之前,siTurn 可能会保持递增。
我知道我应该以更好的方式使用信号量 s2,并尝试从中受益,而不是将其用作互斥体。 任何新的解决方案或修复我当前的解决方案?或使用信号量的通用解决方案,以便我可以将其应用于我的代码。
【问题讨论】:
-
请更改语言标签。这不是 C++。
-
Re, "...那么我应该让所有 10 个线程按照它们的 TID 顺序启动。"这是一个很大的红色警告标志。任何时候你认为你希望不同的线程以特定的顺序做事,你应该重新考虑线程是否是解决问题的正确方法。线程被发明来解决的最初问题是如何为彼此独立发生的不同活动编写代码。这仍然是线程最擅长的。
-
Re,“我正在尝试让所有线程先完成 Phase1,然后再任何线程 [开始] phase2。”与其让线程分别做两件事情,不如将tasks 提交到thread pool?首先,提交十个“第一阶段”任务。然后,当这些都完成后,您可以提交十个“阶段 2”任务。
标签: java multithreading semaphore pthread-barriers