• 【线程同步】屏障


    屏障

    屏障(barrier)是用户协调多个线程并行工作的同步机制,屏障允许每个线程等待,直到合作线程都达到某一点,然后从该点继续执行。我们已经看到一种屏障,pthread_join 函数就是一种屏障,允许一个线程等待,直到另一个线程退出。

    1. 函数原型:初始化和回收

    int pthread_barrier_init(pthread *barrier, const pthread_barrier_t *attr, unsigned int count);
    int pthread_barrier_destroy(pthread_barrier_t *barrier);

    分析:初始化屏障时,可以使用count参数指定,在允许所有线程运行之前,必须到达屏障的线程数目。

    2. 函数原型:

    #include <pthread.h>
    int pthread_barrier_wait(pthread_barrier_t *barrier);

    分析:

    • 每一个线程调用等待函数,barrier 计数都会加 1,直到计数值等于初始化函数中的参数 count。当最后一个线程让 barrier 计数值达到了 count,所有等待的线程都会被唤醒。
    • 所有线程中,只有一个线程会让 pthread_barrier_wait 返回 PTHREAD_BARRIER_SERIAL_THREAD,而其它线程调用此函数会返回 0.

    实验

    程序 barrier 一共有 11 个线程,包含主线程。所有线程会先打印一遍 “hello, I’m thread xx” 然后调用 pthread_barrier_wait 等待,直到 barrier 计数达到了 11 才返回。一旦返回了,就会打印 thread xx returning xx.

    程序清单清单

    #include <unistd.h>
    #include <stdio.h>
    #include <pthread.h>
    
    pthread_barrier_t b;
    
    void* th_fn(void *arg) {
      int id = (pthread_t)arg;
      int res = 0;
      printf("hello, I'm thread [%d]\n", id);
      res = pthread_barrier_wait(&b);
      printf("thread [%d] returning [%d]\n", id, res);
      return NULL;
    }
    
    int main() {
      int i, res = 0;
      pthread_t tid[10];
      printf("PTHREAD_BARRIER_SERIAL_THREAD = %d\n", PTHREAD_BARRIER_SERIAL_THREAD);
    
      pthread_barrier_init(&b, NULL, 11);
    
      for (i = 0; i < 10; ++i) {
        pthread_create(&tid[i], NULL, th_fn, (void*)i);
      }
    
      res = pthread_barrier_wait(&b);
      printf("thread [main] returning [%d]\n", res);
    
      for (i = 0; i < 10; ++i) {
        pthread_join(tid[i], NULL);
      }
    
      pthread_barrier_destroy(&b);
      return 0;
    }

    编译与运行:

    $ gcc barrier.c -o barrier -lpthread
    $ ./barrier

    输出:

  • 相关阅读:
    使用MSXML2::IXMLDOMDocument2Ptr每次都要CreateInstance和load(xmlfile)吗?
    .Net程序安装打包的一些经验贡献
    感慨SQL2005中的数据挖掘算法
    COM客户端没法激活托管代码生成的COM Server的原因
    预感~=命中注定
    创业经理10大必备素质
    全局缓存管理工具
    XML DOM的结构概念图解哪里是Element,哪里是Attribute,哪里是Text
    用GetVolumeInformation得到的不是硬盘的序列号,不要再抄这样的错误好吗?
    站在生活的背后
  • 原文地址:https://www.cnblogs.com/sunbines/p/16473666.html
Copyright © 2020-2023  润新知