【问题标题】:Does using pthread_barrier_wait ensures variable visibility?使用 pthread_barrier_wait 是否确保变量可见性?
【发布时间】:2014-04-09 20:50:01
【问题描述】:

在下面的伪c程序中:

int shared;
pthread_barrier_t b;

// Thread 1
shared = 42;
pthread_barrier_wait(&b);

// Thread 2
pthread_barrier_wait(&b);
int v = shared;
printf("shared = %d\n", v);

POSIX 标准是否确保线程 2 总是打印 42 ? (我在 X86 上运行这个程序) 我花了一些时间阅读内存一致性模型(X86 的 TSO)和缓存一致性协议,我想知道我的问题的答案是否是肯定的,诸如 NPTL 之类的 pthread 实现如何保证这一点?如果答案是否定的,我应该怎么做才能确保始终打印 42?

此外,我有兴趣学习有关手动编写此类障碍(旋转障碍)的解决方案,并保证线程 1 在障碍之前写入的值始终被障碍之后的线程 2 看到。

【问题讨论】:

    标签: c pthreads sync


    【解决方案1】:

    是的,只要你正确初始化屏障,计数为 2

    here 记录的函数充当完整的内存(和编译器)屏障,这意味着在调用这些函数之前执行的内存存储/加载对这些函数之后的其他线程可见。 (并且内存加载/存储不会在这些调用之间移动)

    【讨论】:

    • 句子“以下函数相对于其他线程同步内存:... pthread_barrier_wait ...”是说 pthread_barrier_wait 充当完整的内存屏障?您能否详细说明 pthread 实现的方式,使用 mfence 吗?
    • 是的,这是一个完整的内存屏障。不,pthreads 只是一个规范——它没有实现任何东西。一个特定的实现需要做任何需要保证的事情。 (例如,在 x86 处理器上发出 mfence 指令)
    • 抱歉,我要求的是 NTPL 实施?我之所以这么问,是因为我很想了解其中的内部情况,并且在花时间阅读该主题后无法在脑海中清晰地描绘出来。更准确地说,我不确定在使用 TSO 内存模型的 x86 上是否需要 mfence 指令
    • 实现该功能所需的原子比较和交换已经足以提供内存屏障语义。不需要“mfence”。 (而且通常 mfence 在内置强大的内存一致性保证的 x86 上几乎没用。
    • @R.. 非常感谢这条评论证实了我的想法。 CAS 是否足以用于屏障语义,因为它还“实现”了屏障还是因为 TSO 内存模型?
    【解决方案2】:

    在创建线程之前,您应该使用线程数初始化结构。

    #define THREADS 2
    pthread_barrier_init(&b, NULL, THREADS)
    

    此时,pthread 将确保两个线程都不会从 pthread_barrier_wait(&b); 返回,直到它们都到达它,所以你应该看到 42 打印出来。

    【讨论】:

      猜你喜欢
      • 2017-08-09
      • 2018-02-28
      • 2021-07-15
      • 2011-07-30
      • 2015-07-06
      • 1970-01-01
      • 1970-01-01
      • 2011-02-09
      • 2015-10-20
      相关资源
      最近更新 更多