c-为多线程创建屏障



我正在从mits081(链接(执行屏障任务

要做的事情是实现函数屏障,以阻止线程向前移动,直到所有线程都到达为止。我的实现有时失败,有时成功,所以我在barrier函数中打印出一些信息来帮助调试printf("%d :%dn", bstate.nthread, syscall(__NR_gettid));当成功时,输出将类似

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 :%dn", 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 nthreadn", 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("%dn", syscall(__NR_gettid));
}

for (i = 0; i < nthread; i++)
{
assert(pthread_join(tha[i], &value) == 0);
}
printf("OK; passedn");
}

您需要对同时从多个线程读取/写入的变量的所有访问才能同步。您当前没有在barrier()中锁定互斥体,这会导致竞争条件和未定义的行为。你的pthread_cond_wait也可能因为虚假唤醒而醒来,所以你需要在每次醒来时检查情况(是时候开始下一轮了(。

修复示例:

static void barrier() {
// lock the mutex:
pthread_mutex_lock(&bstate.barrier_mutex);
printf("%d :%ldn", ++bstate.nthread, syscall(__NR_gettid));
if(bstate.nthread == nthread) {
// wake up every thread sleeping on cond
printf("round %d donen", 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函数也在没有同步的情况下从变量(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;
}

最新更新