线程总结3-屏障

本文深入探讨了线程同步中的屏障机制,介绍了屏障的基本概念、相关函数如初始化与wait函数,以及通过两个实例展示了其在多线程任务协调中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线程总结3-屏障

0. 屏障

屏障是用户协调多个线程并行工作的同步机制。屏障允许所有的合作线程都到达某一点,然后从该点继续执行。

1. 相关函数

1.1. 初始化

#include<pthread.h>
int pthread_barrier_init(pthread_barrier_t *restrict barrier,
                        const pthread_barrierattr_t *restrict attr, 
                        unisgned int count);
int pthread_barrier_destory(pthread_barrier_t *barrier);

count 参数设置允许所有线程继续执行之前吗,必须达到屏障的线程数目。

1.2. wait函数

int pthread_barrier_wait(pthread_barrier_t *barrier);

调用pthread_barrier_wait函数的线程在屏障计数没有达到count时,会进入休眠状态。如果该线程是最后一个调用pthread_barrier_wait的线程,就满足了屏障计数,所有线程都会被唤醒。

对于一个任意线程,pthread_barrier_wait函数返回了PTHREAD_BARRIER_SERIAL_THREAD。剩下的线程看到的返回值都是0。这使得一个线程可以作为主线程,它可以工作在其他所有线程已完成的工作结果上。

2. 例程

例程1: 老师给10个学生各自分配一个task,task难易程度不同,因此耗时也不尽相同。每个学生完成自己的task后,输出"task[i] accomplished in m minutes!"。等到所有同学都完成了各自任务,老师宣布"mission accomplished!"

#include<pthread.h>
#define NTHR 10
void* task(void *arg);

pthread_barrier_t barrier;

int main()
{
    int err, i;
    pthread_t tid;

    pthread_barrier_init(&barrier, NULL, NTHR + 1);
    for (i = 0; i < NTHR; i++) {
        err = pthread_create(&tid, NULL, task, (void*)(i));
        if (err != 0) {
            printf("create thread error!\n");
            return -1;
        }
    }
    pthread_barrier_wait(&barrier);
    printf("mission accomplished!\n");
    return 0;
}

void* task(void *arg)
{
    int i, t;

    i = (int)arg;
    t = rand() % 10 + 1;
    // 睡几秒钟,假装我们在执行任务
    sleep(t); 
    printf("task %d accomplished in %d minutes\n", i, t);
    pthread_barrier_wait(&barrier);
    return ((void*)0);
}

完整例程参见barrier-ex01.c

例程2: 对1000万个随机数进行排序。

在这个例子中,我们创建了100个线程,每个线程对10万个数字进行堆排序,排序完成后,在主线程进行合并。

int main()
{
    int err, i;
    pthread_t tid;
    printf("INT_MAX = %d\n", INT_MAX);

    srand(time(NULL));  
    for (i = 0; i < NUMNUM; i++) {
        // sleep_ms(1);
        nums[i] = rand() % INT_MAX;
    }

    // 初始化barrier
    pthread_barrier_init(&barrier, NULL, NTHR + 1);
    // 创建100个排序线程
    for (i = 0; i < NTHR; i++) {
        err = pthread_create(&tid, NULL, sort, (void*)(i * TNUM));
        if (err != 0) {
            printf("create thread error!\n");
            return -1;
        }
    }
    
    pthread_barrier_wait(&barrier);
    //合并排序结果
    merge();
    printf("-------------------------------------\n");
    for (i = 0; i < NUMNUM; i++) {
        // nums[i] = random();
        printf("%10d \n", nums[i]);
        if ((i + 1) % TNUM == 0) {
            printf("-------------------------------------\n");
        }
    }
    return 0;
}

完整例程参见barrier-ex02.c

3.参考资料

[1.] 《unix环境高级编程》第11章

### Java `volatile` 关键字与内存屏障的有序性总结 #### 1. **什么是内存屏障** 内存屏障是一种同步机制,用于确保某些操作在特定顺序下完成。它是一个硬件级别的指令,在多核处理器环境中防止编译器优化或 CPU 的乱序执行行为。通过插入内存屏障,可以强制使屏障前后的读写操作按照指定顺序发生[^1]。 #### 2. **Volatile 和 内存屏障的关系** 当变量被声明为 `volatile` 后,Java 编译器会在对该变量进行读写操作时自动插入相应的内存屏障。具体来说: - 对于 `volatile` 变量的写入操作,会触发一个释放屏障 (Release Barrier),这确保在此之前的任何写操作都会先于该 `volatile` 写操作完成。 - 对于 `volatile` 变量的读取操作,则会触发一个获取屏障 (Acquire Barrier),从而保证此之后的任何读操作都不会提前到这个 `volatile` 读操作之前[^4]。 #### 3. **代码示例分析** 以下是基于提供的代码片段来说明 `volatile` 如何利用内存屏障保障有序性的: ```java public class MemoryBarrierExample { private int num; private volatile boolean ready; public void actor2(I_Result r) { num = 2; // 普通写操作 ready = true; // Volatile 写操作,带有 Release Barrier // 所有在此之前的操作(num=2)都被提交并可见给其他线程 } public void actor1(I_Result r) { if (ready) { // Volatile 读操作,带有 Acquire Barrier // 防止后续读取 num 提前至本语句之前 r.r1 = num + num; // 安全依赖于前面的条件判断 } else { r.r1 = 1; } } } ``` 在这个例子中: -线程调用 `actor2()` 方法并将 `ready` 设置为 `true` 时,由于这是一个 `volatile` 写操作,因此 JVM 自动在其前后插入了一个释放屏障。这意味着所有在线程 A 中发生在设置 `ready=true` 之前的修改(如 `num=2`),都将对其他线程变得可见。 - 在另一个线程中,如果检测到了 `ready==true` (即发生了 `volatile` 读操作),则因为存在获取屏障,所以能够确信此时看到的是最新状态下的数据,并且不会出现因重排序而导致逻辑错误的情况[^2]。 #### 4. **Volatile 的局限性** 尽管 `volatile` 能够很好地提供内存可见性和一定程度上的有序性支持,但它并不能替代锁 (`synchronized`) 来处理复杂的并发场景。特别是对于复合动作或者涉及多个共享资源的状态更新而言,仅靠 `volatile` 并不足以满足原子性需求[^3]。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值