gpt4 book ai didi

CyclicBarrier 中的 C++ 倒计时使用原子变量出错 [请使用无锁解决方案]

转载 作者:行者123 更新时间:2023-11-28 04:34:29 25 4
gpt4 key购买 nike

我正在尝试从头开始在 C++ 中实现循环屏障。目标是实现尽可能符合 Java 实现。类引用在这里。 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html

现在,在我的测试中,returnStatus 应该针对成功越过障碍的每个线程,其值范围从 barrierLimit-1 到零。我正在尝试使用原子变量和内存栅栏来实现这一点。但我的代码测试失败,在某些情况下,两个线程的 returnStatus 值相同。

如果有任何技术可以帮助解决这个问题,请有人提出建议。我想在不使用锁的情况下解决这个问题,这样我就可以真正尽可能多地应用无锁行为。

完整的代码引用位于:https://github.com/anandkulkarnisg/CyclicBarrier/blob/master/CyclicBarrier.cpp

Sample test case result is below [ buggy case ]:

I am currently in thread id = 140578053969664.My barrier state count is = 4
I am currently in thread id = 140577877722880.My barrier state count is = 2
I am currently in thread id = 140577550407424.My barrier state count is = 1
I am currently in thread id = 140577936471808.My barrier state count is = 2
I am currently in thread id = 140577760225024.My barrier state count is = 0


The code snippet is below.

// First check and ensure that the barrier is in good / broken state.
if(!m_barrierState && !m_tripStatus)
{
// First check the status of the variable and immediately exit throwing exception if the count is zero.
int returnResult;
if(m_count == 0)
throw std::string("The barrier has already tripped. Pleas reset the barrier before use again!!" + std::to_string(returnResult));

// First ensure that the current wait gets the waiting result assigned immediately.

std::atomic_thread_fence(std::memory_order_acquire);
m_count.fetch_sub(1, std::memory_order_seq_cst);
returnResult = m_count.load();
std::atomic_thread_fence(std::memory_order_release);

最佳答案

std::atomic_thread_fence(std::memory_order_acquire);
m_count.fetch_sub(1, std::memory_order_seq_cst); // [1]
returnResult = m_count.load(); // [2]
std::atomic_thread_fence(std::memory_order_release);

[2] 多个线程同时在做这个步骤。 std::atomic_thread_fence 不会阻止其他线程同时运行相同的代码。这就是 2 个线程最终会得到相同值的原因。

相反,在标有 [1]

的行上捕获 fetch_sub 的返回值

returnResult = m_count.fetch_sub(1, std::memory_order_seq_cst) - 1;

顺便说一句,我很确定你不需要这里的栅栏。 (如果没有看到更多的功能,我真的无法分辨。)如果你这样做,你可能只是将 returnResult 切换为原子。

看起来您正在使用栅栏,就好像它们是事务内存一样。他们不是。当任何使用 acquire 的 CPU 感知时,释放本质上控制存储排序的保证。只要不破坏顺序保证,写入就可以在实际处理发布之前自由传播。作为一个思想实验,假设 [1] 被执行,然后发生上下文切换,一百万年过去了,然后 [2] 被执行。现在假设 m_count 与一百万年前的值相同显然是荒谬的。发布可能会刷新写入缓冲区,但更改可能已被刷新。

最后,如果将 seq_cstacquire/release 语义混合使用,可能会发生奇怪的事情。抱歉,这很含糊,但我对它的理解还不够深入,无法解释。

关于CyclicBarrier 中的 C++ 倒计时使用原子变量出错 [请使用无锁解决方案],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51868241/

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