线程同步之屏障属性
屏障的作用是允许每个线程完成自身任务之后等待,直到所有线程都达到某一点,然后从该点继续执行。
默认情况下屏障应用于单个进程的多个线程之间。
屏障的进程共享属性允许将屏障应用于多个进程之间,前提是多个进程能够访问到同一个屏障对象。
属性介绍
数据类型:pthread_barrierattr_t
。
初始化与反初始化函数:
#include <pthread.h>
int pthread_barrierattr_destroy(pthread_barrierattr_t* attr);
int pthread_barrierattr_init(pthread_barrierattr_t* attr);
// 返回值:成功返回0,失败返回错误编号
pthread_barrierattr_init()
函数将屏障属性初始化为默认值。
进程共享属性
作用:该进程共享属性控制着屏障是可以被多进程的线程使用,还是只能被初始化屏障的进程内的多线程使用。
取值:PTHREAD_PROCESS_SHARED
与PTHREAD_PROCESS_PRIVATE
。
获取与设置函数:
#include <pthread.h>
int pthread_barrierattr_getpshared(const pthread_barrierattr_t* restrict attr, int* restrict pshared);
int pthread_barrierattr_setpshared(pthread_barrierattr_t* attr, int pshared);
// 返回值:成功返回0,失败返回错误编号
示例
下面的示例主要有ChatGPT3.5来生成,并在此基础上做了一点修改。
示例中,在5个进程中使用屏障的进程共享属性。
屏障在初始化时,如果屏障计数大于pthread_barrier_wait()
函数的调用次数并且屏障没有被销毁,那么会启动第二次屏障阻塞,以等待再次同步。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define NUM_PROCESSES 5
pthread_barrier_t* barrier;
void* threadFunction(void* arg)
{
int processId = *(int*)arg;
printf("Process %d: Hello!\n", processId);
printf("Process %d: Goodbye!\n", processId);
pthread_barrier_wait(barrier);
printf("Process %d: barrier finish\n", processId);
return NULL;
}
int main()
{
pid_t processIds[NUM_PROCESSES];
// 创建共享内存
barrier = mmap(NULL, sizeof(pthread_barrier_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
// 初始化屏障
pthread_barrierattr_t attr;
pthread_barrierattr_init(&attr);
pthread_barrierattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
// 如果不加1,会导致有个进程无法退出,因为到达屏障计数后,屏障会重新计数,直到再次到达屏障计数
pthread_barrier_init(barrier, &attr, NUM_PROCESSES + 1);
pthread_barrierattr_destroy(&attr);
// 创建子进程
for (int i = 0; i < NUM_PROCESSES; i++)
{
processIds[i] = fork();
if (processIds[i] == 0)
{
int processId = i + 1;
pthread_t thread;
pthread_create(&thread, NULL, threadFunction, &processId);
pthread_join(thread, NULL);
exit(0);
}
}
pthread_barrier_wait(barrier);
printf("Main Process: barrier wait finish\n");
// 等待子进程结束
for (int i = 0; i < NUM_PROCESSES; i++)
waitpid(processIds[i], NULL, 0);
// 销毁屏障
pthread_barrier_destroy(barrier);
// 释放共享内存
munmap(barrier, sizeof(pthread_barrier_t));
return 0;
}
// Process 1: Hello!
// Process 1: Goodbye!
// Process 2: Hello!
// Process 2: Goodbye!
// Process 3: Hello!
// Process 3: Goodbye!
// Process 5: Hello!
// Process 5: Goodbye!
// Process 4: Hello!
// Process 4: Goodbye!
// Process 1: barrier finish
// Process 2: barrier finish
// Process 4: barrier finish
// Main Process: barrier wait finish
// Process 5: barrier finish
// Process 3: barrier finish
- 原文作者:生如夏花
- 原文链接:https://blduan.top/post/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/apue/%E7%BA%BF%E7%A8%8B%E5%90%8C%E6%AD%A5%E4%B9%8B%E5%B1%8F%E9%9A%9C%E5%B1%9E%E6%80%A7/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。