0

我正在尝试编写多线程代码,但我遇到了一个小问题。在我的程序中,我有两种类型的线程,explorers(我有 4 个或 5 个)和 main(我有一个)。我希望所有资源管理器线程同时运行,当它们都完成后,主线程开始工作。有一个循环,我一遍又一遍地做上面的事情。由于线程创建的开销,我决定让资源管理器线程在 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 用于在结束 explorer 之前阻止 main 运行,barrier_2 用于在结束 main 之前阻止 explorer。

我的问题是这段代码不能完全正确。一开始它工作正常,但经过两三次迭代后,一些资源管理器线程突然停止工作,因此整个程序将停止工作。

我无法弄清楚,特别是因为迭代次数没有规则。在某些运行中,它在第一次迭代后停止,在另一些运行中,它可以正常工作到第 5 次或第 6 次。

顺便说一句,我正在使用 Mac OSX。

4

2 回答 2

2

在没有看到实际代码的情况下尽可能地回答,在资源管理器线程有 reset_barrier_2之前,main 似乎有可能通过 wait_for_barrier_2。

所以 main 循环回到 wait_for_barrier_1,然后资源管理器线程 reset_barrier_2 和 wait_for_barrier_2。这样 main 等待 1,explorers 等待 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 之前重置_barrier_2 可能会起作用,这样 main 在重置之前将无法冲过 wait_for_barrier_2。

于 2013-06-28T23:39:47.553 回答
0

实际上问题会出现,因为当您重置障碍时,它会丢失记忆并忘记之前有多少线程到达它。因此,例如,资源管理器可能会等待 Barrier1,然后时间转到主通道,主通道 Barrier1 完成其工作并在资源管理器有机会通过它之前将其重置。所以在这种情况下,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-29T22:29:32.860 回答