我正在试着写一个多线程的代码,但是我遇到了一个小问题。在我的程序中,我有两种类型的线程,explorers (我有4到5个)和main (我有一个)。我希望所有的资源管理器线程同时运行,当它们都完成后,主线程开始它的工作。有一个循环,我一遍又一遍地做上面的事情。由于线程创建的开销,我决定让Explorer线程在main运行时休眠,并在它完成时唤醒它(当然,反之亦然)。为了实现这个目标,我使用了屏障。下面是我的线程的伪代码:
主线程函数:
void* main(void* arg)
{
while(true)
{
wait_for_barrier_1
do_your_job
reset_barrier_1
wait_for_barrier_2
}
}资源管理器线程函数
void* explorers(void* arg)
{
while(true)
{
do_your_job
wait_for_barrier_1
if(thread_id == 0)
{
reset_barrier_2
}
wait_for_barrier_2
}
}barrier_1用于在结束资源管理器之前防止主程序运行,barrier_2用于在结束主程序之前防止资源管理器运行。
我的问题是这段代码不能完全正确地工作。一开始它工作得很好,但在两到三次迭代后,一些资源管理器线程会突然停止工作,因此整个程序也会停止工作。
我想不出来,特别是因为迭代的次数没有规则。在一些运行中,它在第一次迭代后停止,在另一些运行中,它工作得很好,直到第五次或第六次迭代。
顺便说一句,我使用的是Mac。
发布于 2013-06-30 06:29:33
实际上,问题之所以出现,是因为当你重置一个障碍时,它失去了记忆,忘记了以前是如何有那么多线程到达它的。举个例子,可能explorer在等待Barrier1,然后时间转到main,main pass Barrier1完成它的工作,并在explorer有机会传递它之前重置它。因此,在这种情况下,main正在等待Barrier2,而explorer正在等待Barrier1 (由main重置)
为了解决这个问题,我为每个屏障使用了两个屏障变量,并在迭代中在它们之间切换。以下是我的伪代码。它工作得很好。
主要功能:
void* main(void* arg)
{
bool turn = false;
while(true)
{
if(turn)
{
wait_for_barrier_1
}
else
{
wait_for_barrier_1_P
}
do_your_job
if(turn)
{
reset_barrier_1_P
}
else
{
reset_barrier_1
}
if(turn)
{
wait_for_barrier_2
}
else
{
wait_for_barrier_2_P
}
turn = !turn ;
}
}资源管理器功能:
void* main(void* arg)
{
bool turn = false;
while(true)
{
do_your_job
if(turn)
{
reset_barrier_2
}
else
{
reset_barrier_2_P
}
if(turn)
{
wait_for_barrier_1
}
else
{
wait_for_barrier_1_P
}
if(turn)
{
wait_for_barrier_2
}
else
{
wait_for_barrier_2_P
}
turn = !turn ;
}
}我知道它有点乱,但它工作得很好。
发布于 2013-06-29 07:39:48
在没有看到实际代码的情况下尽我所能地回答,似乎有可能main在资源管理器线程具有reset_barrier_2之前通过wait_for_barrier_2传递。
所以主循环返回到wait_for_barrier_1,然后资源管理器线程reset_barrier_2和wait_for_barrier_2。这样,主线程等待1,资源管理器等待2,没有人继续。
如下所示:
Iteration 1:
main wait_for_barrier_1
explorers do_your_job
explorers wait_for_barrier_1
main do_your_job
explorers reset_barrier_2
explorers wait_for_barrier_2
main reset_barrier_1
main wait_for_barrier_2
main wait_for_barrier_1…
Iteration 2:
…main wait_for_barrier_1
explorers do_your_job
explorers wait_for_barrier_1
main do_your_job
main reset_barrier_1
main wait_for_barrier_2 (but it hasn't been reset yet! Runs right through!)
main wait_for_barrier_1
explorers reset_barrier_2
explorers wait_for_barrier_2
Deadlock!我认为如果你在wait_for_barrier_1之前先reset_barrier_2,那么main就不能在重置之前匆忙通过wait_for_barrier_2了。
https://stackoverflow.com/questions/17375002
复制相似问题