如何使用fetch_sub和atomic_thread_fence递减多线程?
how to decrement mutithreaded using fetch_sub and atomic_thread_fence?
我们有一个成员方法(bool try(((,它应该是线程安全的,如果变量大于0,它会递减变量m_count,我们尽量避免互斥锁,而是使用fetch_sub和atomic_thread_fence。
struct Test {
bool try() {
if (m_count<1)
return false;
int count = m_count.fetch_sub(1, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);
return true;
}
Test():m_count(1) {}
private:
std::atomic<int> m_count;
}
我们希望确保 m_count 永远不会小于 0,并且如果 try 递减m_count则返回 true。上面的两个线程可以将m_count从 1 递减到 -1,这是不可接受的。
负载if (m_count<1)
和调用fetch_sub()
之间存在间隙。
假设m_count == 1
,一个线程执行加载并继续,但在它执行fetch_sub()
之前,第二个线程执行加载并获得相同的值(1
(。现在两个线程都将执行fetch_sub()
,m_count
变得-1
。
若要消除此差距,可以将比较和修改合并到单个原子比较和交换 (CAS( 操作中,如下所示:
bool do_try() {
bool modified=false;
int current = m_count.load(std::memory_order_relaxed);
do {
if (current == 0)
break;
assert(current > 0);
} while (!(modified = m_count.compare_exchange_weak(current, current-1, std::memory_order_relaxed)));
std::atomic_thread_fence(std::memory_order_acquire);
return modified;
}
现在m_count
不能成为-1
.
如果compare_exchange()
返回false
,它将使用最新值更新其第一个参数,因此您不必再次调用load()
。
相关文章:
- 在std::thread中,joinable()然后join()线程安全吗
- <Windows>为什么 std::thread::native_handle 返回类型为"long long unsigned int"的值,而不是 void*(又名 HANDLE)?
- 分离一个静态常量 std::thread?
- 尝试使用 std::vector<std::thread时出现静态断言失败错误>
- 使用 thread 类在 C++ 中构造线程的动态数组时出错
- 当指向对象的指针作为参数传递给 std::thread 时,内存可见性
- 如何从 std::thread 返回值
- 在C++中使用并行化的预期速度是多少(不是 OpenMp,而是 <thread>)
- 将 std::thread by 值推送到列表中
- 转发变量参数列表以模拟 std::thread
- 嵌入式设备 -> std::thread -> FreeRTOS?
- 对 'std::thread::_M_start_thread CMake 的未定义引用进行基准测试
- std::thread 增加 DLL 引用计数,从而防止卸载 DLL
- 如何防止 std::thread 在 QT 中冻结 GUI?
- 对带有唯一指针的 std::thread 使用类成员函数时出现编译错误
- C++ - Thread Pool
- 为什么参数在构造 std::thread 时移动两次
- std::thread::_Invoker 使用线程编程时出错
- 在线程 A 中创建一个 std::thread 对象,在线程 B 中连接
- 为什么编译器抱怨 std::thread 参数在转换为右值后必须是可调用的?