1

我正在创建 n 个线程,然后在障碍击穿后开始执行。

在全局数据空间中:

int bkdown = 0;

在 main() 中:

pthread_barrier_init(&bar,NULL,n);

for(i=0;i<n;i++)
{
pthread_create(&threadIdArray[i],NULL,runner,NULL);
if(i==n-2)printf("breakdown imminent!\n");
if(i==n-1)printf("breakdown already occurred!\n");
}

在线程运行器功能中:

void *runner(void *param)
{
 pthread_barrier_wait(&bar);

 if(bkdown==0){bkdown=1;printf("barrier broken down!\n");}

        ...

 pthread_exit(NULL);
}

预期顺序:

breakdown imminent!
barrier broken down!
breakdown already occurred!

实际订单:( 反复测试)

breakdown imminent!
breakdown already occurred!
barrier broken down!!

有人可以解释为什么我在"broken down"消息之前没有收到"already occurred"消息吗?

4

4 回答 4

3

线程运行的顺序取决于操作系统。仅仅因为您启动一个线程并不意味着操作系统会立即运行它。

如果你真的想控制线程的执行顺序,你必须在其中放置某种同步(使用互斥锁或条件变量。)

于 2010-09-24T19:43:06.227 回答
2
for(i=0;i<n;i++)
{
pthread_create(&threadIdArray[i],NULL,runner,NULL);
if(i==n-2)printf("breakdown imminent!\n");
if(i==n-1)printf("breakdown already occurred!\n");
}

没有什么能阻止这个循环执行直到i == n-1。pthread_create() 只是触发要运行的线程。它不会等待它开始或结束。因此,您受调度程序的支配,它可能决定继续执行您的循环,或切换到新创建的线程之一(或在 SMP 系统上同时执行这两项操作)。

您还初始化了对 的障碍n,因此在任何情况下,在您创建所有线程之前,没有一个线程会越过障碍。

于 2010-09-24T19:44:41.403 回答
1

除了 nos 和 Starkey 的答案之外,您还必须考虑到您的代码中还有另一个经常被忽略的序列化:您正在同一个FILE变量上执行 IO,即stdin.

对该变量的访问在内部是互斥的,并且您的n+1线程(包括您的调用线程)访问该互斥的顺序是实现定义的,在您的情况下基本上将其视为随机。

所以你得到printf输出的顺序就是你的线程穿过这些虫洞的顺序。

于 2010-09-24T21:36:50.033 回答
0

您可以通过以下两种方式之一获得预期的订单

  • 创建优先级高于主线程的每个线程。这将确保新线程在创建后立即运行并在屏障上等待。
  • 将“故障迫在眉睫!\n”打印移到 pthread_create() 之前,并在每个 pthread_create() 之后调用使用 sched_yield() 调用。这将安排新创建的线程执行。
于 2011-05-20T08:33:37.290 回答