在我的程序中,2 个线程以矛盾(用于测试)的方式对一个简单数组进行排序。唯一的想法是防止两个线程同时使用 std::atomic 对数组进行排序。预期的结果是数组将根据“赢家线程”进行降序或升序排序。 我知道这可以很容易地用互斥量解决,但我只是在这里尝试了解 std::atomic 的好处。我的程序在所有执行案例中有 10% 失败:失败是两种情况交织在一起时...在此先感谢您的任何突出显示...
std::array<int, 5> my_array{ 1, 4, 3, 2, 5 };
std::atomic< std::array<int, 5>* > my_array_{ &my_array };
std::thread my_thread(
[&my_array_]() {
std::array<int, 5>* my_array = nullptr;
do { my_array = my_array_.load(std::memory_order_acquire); } while (my_array == nullptr);
my_array_.store(nullptr, std::memory_order_release);
std::sort(my_array->begin(), my_array->end(),
[](const int a, const int b) {
// std::cout << "\tascending a: " << a << " b: " << b << std::endl;
return a > b;
});
my_array_.store(my_array, std::memory_order_release);
});
std::thread my_thread_(
[&my_array_]() {
std::array<int, 5>* my_array = nullptr;
do { my_array = my_array_.load(std::memory_order_acquire); } while (my_array == nullptr);
my_array_.store(nullptr, std::memory_order_release);
std::sort(my_array->begin(), my_array->end(),
[](const int a, const int b) {
// std::cout << "\tdescending a: " << a << " b: " << b << std::endl;
return a < b;
});
my_array_.store(my_array, std::memory_order_release);
});
my_thread_.join();
my_thread.join();
for (const int i : my_array)
std::cout << "\t" << i;
最佳答案
如果您想使用my_array_
原子变量来指示某个线程是否已声明它,那么您可以简单地调用
auto local_array=my_array_.exchange(nullptr)
来自您的线程。如果这是第一个进行交换的线程,local_array
将因此成为指向 my_array
的指针,如果另一个线程首先到达那里,则 nullptr
。
就目前而言,通过简单的加载和存储,然后两个线程都可以读取 my_array_
指针并看到它不是 nullptr
,然后都可以存储 nullptr
在里面,并且都认为他们先到达那里。
此外:使用 my_array
作为全局名称,和 本地指针的名称会造成混淆。
关于C++ std::atomic - 不可能基于共享原子变量同步 2 个线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59047226/