[英]Creating a Barrier for multi-thread
我正在执行 mits081 的屏障任务(链接)
要做的是实现 function 屏障,以阻止线程向前移动,直到所有线程都到达。 我的实现有时会失败,有时会成功,所以我在屏障 function 内打印出一些信息来帮助调试printf("%d:%d\n", bstate.nthread, syscall(__NR_gettid));
成功后,output 会像
0 :81906
0 :81907
0 :81907
0 :81906
0 :81906
1 :81907
0 :81906
1 :81907
0 :81906
0 :81907
0 :81907
0 :81906
0 :81907
0 :81906
0 :81906
1 :81907
0 :81907
0 :81906
0 :81906
1 :81907
OK; passed
失败时,如图所示打印最后一行后会卡住。
0 :81909
0 :81910
0 :81910
1 :81909
0 :81910
0 :81909
0 :81909
0 :81910
0 :81909
1 :81910
0 :81910
1 :81909
0 :81909
1 :81910
0 :81910
1 :81909
0 :81909
1 :81910
0 :81910
1 :81909
有人可以告诉我我的实施有什么问题吗? 提前致谢
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <assert.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>
static int nthread = 1;
static int round = 0;
struct barrier
{
pthread_mutex_t barrier_mutex;
pthread_cond_t barrier_cond;
int nthread; // Number of threads that have reached this round of the barrier
int round; // Barrier round
} bstate;
static void
barrier_init(void)
{
assert(pthread_mutex_init(&bstate.barrier_mutex, NULL) == 0);
assert(pthread_cond_init(&bstate.barrier_cond, NULL) == 0);
bstate.nthread = 0;
}
static void
barrier()
{
// YOUR CODE HERE
//
// Block until all threads have called barrier() and
// then increment bstate.round.
// //
printf("%d :%d\n", bstate.nthread, syscall(__NR_gettid));
if (++bstate.nthread % nthread == 0)
{
pthread_cond_broadcast(&bstate.barrier_cond); // wake up every thread sleeping on cond
bstate.round++;
}
else
pthread_cond_wait(&bstate.barrier_cond, &bstate.barrier_mutex); // go to sleep on cond, releasing lock mutex, acquiring upon wake up
}
static void *
thread(void *xa)
{
long n = (long)xa;
long delay;
int i;
for (i = 0; i < 10; i++)
{
int t = bstate.round;
assert(i == t);
barrier();
usleep(random() % 100);
}
// printf("a");
return 0;
}
int main(int argc, char *argv[])
{
pthread_t *tha;
void *value;
long i;
double t1, t0;
if (argc < 2)
{
fprintf(stderr, "%s: %s nthread\n", argv[0], argv[0]);
exit(-1);
}
nthread = atoi(argv[1]);
tha = malloc(sizeof(pthread_t) * nthread);
srandom(0);
barrier_init();
for (i = 0; i < nthread; i++)
{
assert(pthread_create(&tha[i], NULL, thread, (void *)i) == 0);
printf("%d\n", syscall(__NR_gettid));
}
for (i = 0; i < nthread; i++)
{
assert(pthread_join(tha[i], &value) == 0);
}
printf("OK; passed\n");
}
您需要对同时从多个线程读取/写入的变量的所有访问权限进行同步。 您目前没有将互斥锁锁定在会导致竞态条件和未定义行为的barrier()
中。 您的pthread_cond_wait
也可能由于虚假唤醒而唤醒,因此您需要在每次唤醒时检查条件(是时候开始下一轮了)。
示例修复:
static void barrier() {
// lock the mutex:
pthread_mutex_lock(&bstate.barrier_mutex);
printf("%d :%ld\n", ++bstate.nthread, syscall(__NR_gettid));
if(bstate.nthread == nthread) {
// wake up every thread sleeping on cond
printf("round %d done\n", bstate.round++);
bstate.nthread = 0;
pthread_cond_broadcast(&bstate.barrier_cond);
} else {
int lround = bstate.round;
// sleep until the next round starts:
do {
pthread_cond_wait(&bstate.barrier_cond, &bstate.barrier_mutex);
} while(lround == bstate.round);
}
// unlock the mutex:
pthread_mutex_unlock(&bstate.barrier_mutex);
}
另请注意,您的thread
function 也会从变量( bstate.round
)中读取,而无需同步,该变量也由其他线程写入。 删除:
static void* thread(void* xa) {
long n = (long)xa;
long delay;
int i;
for(i = 0; i < 10; i++) {
barrier();
usleep(random() % 100);
}
return NULL;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.