C++ pthread中的线程在一些迭代之后停止工作
我正试图编写一个多线程代码,但我有一个小问题。 在我的程序中,我有两种类型的线程,explorer(我有4或5个)和main(我有一个)。我希望所有的探索者线程同时运行,当它们都完成后,主线程开始它的工作。有一个循环,我一遍又一遍地在上面做。由于线程创建的开销,我决定让探索者线程在main运行时休眠,并在完成时唤醒它(当然反之亦然)。为了实现这个目标,我使用了障碍。以下是我的线程的伪代码: 主线程函数:C++ pthread中的线程在一些迭代之后停止工作,c++,pthreads,C++,Pthreads,我正试图编写一个多线程代码,但我有一个小问题。 在我的程序中,我有两种类型的线程,explorer(我有4或5个)和main(我有一个)。我希望所有的探索者线程同时运行,当它们都完成后,主线程开始它的工作。有一个循环,我一遍又一遍地在上面做。由于线程创建的开销,我决定让探索者线程在main运行时休眠,并在完成时唤醒它(当然反之亦然)。为了实现这个目标,我使用了障碍。以下是我的线程的伪代码: 主线程函数: void* main(void* arg) { while(true)
void* main(void* arg)
{
while(true)
{
wait_for_barrier_1
do_your_job
reset_barrier_1
wait_for_barrier_2
}
}
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 ;
}
}
explorers线程函数
void* explorers(void* arg)
{
while(true)
{
do_your_job
wait_for_barrier_1
if(thread_id == 0)
{
reset_barrier_2
}
wait_for_barrier_2
}
}
屏障_1用于在结束总管之前阻止总管,屏障_2用于在结束总管之前阻止总管
我的问题是这个代码不能完全正确工作。开始时,它工作正常,但经过两三次迭代后,一些资源管理器线程会突然停止工作,因此整个程序将停止工作
我搞不清楚,特别是因为迭代次数没有规则。在一些运行中,它在第一次迭代后停止,在另一些运行中,它在第五次或第六次迭代之前工作正常
顺便说一句,我正在使用Mac OSX。在没有看到实际代码的情况下尽可能地回答问题,在资源管理器线程重置\u barrier\u 2之前,main可能正在通过wait\u for\u barrier\u 2 因此,主循环返回以等待\u屏障\u 1,然后浏览器线程重置\u屏障\u 2,并等待\u屏障\u 2。由于main等待1,explorer等待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!
我认为如果在等待等待等待1之前重置2,可能会起作用,这样main就无法在重置之前通过等待2。事实上,问题会出现,因为重置一个屏障时,它会丢失内存,并且忘记了线程之前是如何到达它的。所以举例来说,它可能是浏览器等待Barrier1,然后时间去主,主通行证Barrier1做它的工作,并重置它之前,浏览器有机会通过它。因此,在这种情况下,main正在等待Barrier2,explorer正在等待Barrier1(由main重置) 为了解决这个问题,我对每个屏障使用了两个屏障变量,并在迭代中在它们之间切换。下面是我的伪代码。它工作得很好 主要功能:
void* main(void* arg)
{
while(true)
{
wait_for_barrier_1
do_your_job
reset_barrier_1
wait_for_barrier_2
}
}
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 ;
}
}
浏览器功能:
void* main(void* arg)
{
while(true)
{
wait_for_barrier_1
do_your_job
reset_barrier_1
wait_for_barrier_2
}
}
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 ;
}
}
我知道这有点混乱,但它工作得很好。我们真的需要看看实际的代码。事实上,正如您所说,我在切换命令时遇到了同样的问题。问题是当你重置一个屏障时,它忘记了它的最后一个。所以,有时候,比如说,资源管理器在等待B1,然后时间转到main,main完成它的工作并重置B1,然后资源管理器才有机会通过它并。。。我通过为每个屏障使用两个屏障变量并在迭代中在它们之间切换来解决问题。顺便说一句,谢谢你的想法,它真的鼓励我去寻找那种僵局。