线程同步的障碍

时间:2010-09-24 19:32:31

标签: c pthreads barrier

我正在创建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 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分: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的障碍,所以无论如何,在你创造所有这些线程之前,所有线程都不会越过障碍。

答案 2 :(得分:1)

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

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

因此,获得n+1输出的顺序是线程通过这些虫洞的顺序。

答案 3 :(得分:0)

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

  • 创建优先级高于主线程的每个线程。这将确保新线程在创建后立即运行并等待屏障。
  • 在pthread_create()之前移动“即将崩溃!\ n”打印,并在每个pthread_create()之后调用一次sched_yield()调用。这将安排新创建的线程以供执行。