首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >pthread中的线程在一些迭代后停止工作。

pthread中的线程在一些迭代后停止工作。
EN

Stack Overflow用户
提问于 2013-06-29 07:18:08
回答 2查看 1.1K关注 0票数 0

我正在试着写一个多线程的代码,但是我遇到了一个小问题。在我的程序中,我有两种类型的线程,explorers (我有4到5个)和main (我有一个)。我希望所有的资源管理器线程同时运行,当它们都完成后,主线程开始它的工作。有一个循环,我一遍又一遍地做上面的事情。由于线程创建的开销,我决定让Explorer线程在main运行时休眠,并在它完成时唤醒它(当然,反之亦然)。为了实现这个目标,我使用了屏障。下面是我的线程的伪代码:

主线程函数:

代码语言:javascript
运行
复制
void* main(void* arg)
{
     while(true)
     {
         wait_for_barrier_1

         do_your_job

         reset_barrier_1
         wait_for_barrier_2
     }
}

资源管理器线程函数

代码语言:javascript
运行
复制
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。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-06-30 06:29:33

实际上,问题之所以出现,是因为当你重置一个障碍时,它失去了记忆,忘记了以前是如何有那么多线程到达它的。举个例子,可能explorer在等待Barrier1,然后时间转到main,main pass Barrier1完成它的工作,并在explorer有机会传递它之前重置它。因此,在这种情况下,main正在等待Barrier2,而explorer正在等待Barrier1 (由main重置)

为了解决这个问题,我为每个屏障使用了两个屏障变量,并在迭代中在它们之间切换。以下是我的伪代码。它工作得很好。

主要功能:

代码语言:javascript
运行
复制
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 ;
     }
}

资源管理器功能:

代码语言:javascript
运行
复制
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 ;
     }
}

我知道它有点乱,但它工作得很好。

票数 0
EN

Stack Overflow用户

发布于 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,没有人继续。

如下所示:

代码语言:javascript
运行
复制
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了。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17375002

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档