繁体   English   中英

为多线程创建屏障

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM