gpt4 book ai didi

c - 在 C 中实现线程屏障和屏障重置的正确方法是什么?

转载 作者:行者123 更新时间:2023-12-01 23:51:35 27 4
gpt4 key购买 nike

我试图在我的代码中实现一个简单的屏障,如下所示:

void waitOnBarrier(int* barrier, int numberOfThreads) {
atomicIncrement(barrier); // atomic increment implemented in assembly
while(*barrier < numberOfThreads);
}

然后代码中有一个屏障用法:
int g_barrier = 0; // a global variable

waitOnBarrier(&g_barrier, someKnownNumberOfThreads);

到目前为止一切顺利,但我应该在哪里重置我的 g_barrier 变回零?如果我写类似的东西
g_barrier = 0;

紧跟在 之后waitOnBarrier 调用,如果其中一个线程比其他线程从屏障中释放得更快并且使 无效,我就会遇到问题。 g_barrier 而所有其他线程仍在执行循环指令,因此最终它们将永远卡在屏障上。

解释:
waitOnBarrier 将编译成这样的东西(伪代码):
1: mov rax, numberOfThreads
2: mov rbx, [barrier]
3: cmp rax, rbx
4: jmp(if smaller) to 2

因此,如果我们有 2 个线程在屏障上同步,并且 thread_1 在指令 3 或 4 的某处变慢,而更快的 thread_2 到达屏障,则通过它并继续到 g_barrier 无效流。这意味着在 thread_1 到达指令 2 之后,它会在 [barrier] 处看到一个零值,并将永远停留在屏障上!

问题是,我应该如何取消 g_barrier ,它在代码中的哪个位置“足够远”以至于我可以确定到那时所有线程都离开了障碍?或者是否有更正确的方法来实现障碍?

最佳答案

障碍实际上很难实现,主要原因是新的服务员可以在所有旧服务员有机会执行之前就开始到达,这排除了任何简单的基于计数的实现。我的首选解决方案是让屏障对象本身简单地指向一个“当前屏障实例”,该实例存在于第一个到达屏障的线程的堆栈上,并且也是最后一个离开的线程(因为它不能离开而其他线程仍在引用其堆栈)。关于 pthread 原语(可以适用于 C11 锁定原语或您必须使用的任何内容)方面的一个非常好的示例实现包含在 Michael Burr 对我过去关于该主题的问题的回答中:

https://stackoverflow.com/a/5902671/379897

是的,这看起来需要做很多工作,但是编写一个真正满足屏障契约的屏障实现并非易事。

关于c - 在 C 中实现线程屏障和屏障重置的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26231727/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com