线程同步的障碍
Posted
技术标签:
【中文标题】线程同步的障碍【英文标题】:Barriers for thread syncing 【发布时间】:2011-04-16 23:07:19 【问题描述】:我正在创建 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!!
有人可以解释为什么我在"already occurred"
消息之前没有收到"broken down"
消息吗?
【问题讨论】:
【参考方案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
的屏障,因此在任何情况下,在您创建所有线程之前,所有线程都不会越过屏障。
【讨论】:
【参考方案3】:除了 nos 和 Starkey 的答案之外,您还必须考虑到您的代码中还有另一个经常被忽略的序列化:您正在同一个 FILE
变量上执行 IO,即 stdin
。
对该变量的访问在内部是互斥的,您的n+1
线程(包括您的调用线程)访问该互斥的顺序是实现定义的,在您的情况下基本上是随机的。
因此,您获得printf
输出的顺序就是您的线程通过这些虫洞的顺序。
【讨论】:
【参考方案4】:您可以通过以下两种方式之一获得预期的订单
创建优先级高于主线程的每个线程。这将确保新线程在创建后立即运行并在屏障上等待。 将“故障迫在眉睫!\n”打印移到 pthread_create() 之前,并在每个 pthread_create() 之后调用使用 sched_yield() 调用。这将安排新创建的线程执行。【讨论】:
以上是关于线程同步的障碍的主要内容,如果未能解决你的问题,请参考以下文章