STD :: Atomic在一个简单的POD类中

std::atomic on a simple POD class

本文关键字:简单 一个 POD 类中 Atomic STD      更新时间:2023-10-16

我已经阅读了许多文章和问题,例如这个,这是对此的所有答案,对于在这种情况下实际应采取的措施尚无定论:

目前,我正在编写一个并发程序,在该程序中我需要多次同时访问std::priority_queue<std::pair<int, int>>的大小和顶部,同时在其他地方推动和弹出元素。
但是,每次需要阅读时锁定mutex(对于读者和作家问题的解决方案也不够有效)。

唯一足够好的是将这三个属性包裹在std::atomic中,并在每个队列更新中更新原子,如果只有编译器允许我这样做,则可以使用。

可悲的是,G 7.2.0输出

"未定义的引用'__atomic_load'"

链接时错误消息。

我尝试将-latomic添加到CMakeLists.txt,但我得到了

"/usr/bin/ld:找不到-latomic"

错误(而我不允许更改或更新编译器)。

我的结构是POD类型(我用static_assert检查了),所以我只是不明白为什么它不起作用。我该如何工作?

编辑:我编译了与第三个链接中的代码几乎相同的代码

#include <iostream>
#include <atomic>
using namespace std;
struct Vec {
    int x, y, z;
};
int main() {
    std::atomic<Vec> x;
    Vec a;
    x = a;
}

并收到以下错误消息

CMakeFiles/folder.dir/vec.cpp.o: In function `std::atomic<Vec>::store(Vec, std::memory_order)':
vec.cpp:(.text._ZNSt6atomicI3VecE5storeES0_St12memory_order[_ZNSt6atomicI3VecE5storeES0_St12memory_order]+0x47): undefined reference to `__atomic_store'

collect2:错误:ld返回1退出状态

从评论中移动/扩展:

g std::atomic<T>实现需要非本地支持类型的libatomic。

我可以使用-latomic复制并修复您的错误:

[matteo@teolapkubuntu /tmp]$ g++ -O3 test.cpp
/tmp/cc7YRyMy.o: In function `main':
test.cpp:(.text.startup+0x3f): undefined reference to `__atomic_store'
collect2: error: ld returned 1 exit status
[matteo@teolapkubuntu /tmp]$ g++ -O3 test.cpp -latomic
[matteo@teolapkubuntu /tmp]$ 

仍然,如果您的工具链没有提供libatomic,我不会担心太多。

libatomic中非本地支持类型的原子存储沸腾至比较交换环(请参阅LARGER宏),或者在"脱名式"案例(T大于16个字节)中,到一个普通的Mutex(libat_lock_n使用目标地址的哈希,并锁定来自某个全局锁的相应锁)。

这是您可以在没有太多麻烦的情况下实现自己的所有内容 - 实际上,您的位置比 libatomic 的作者更好,因为您可以添加额外的数据成员目标数据本身或其地址从锁定池。

首先,我会尝试使用一个普通的静音,以保护您的单独的数据副本。鉴于该静音的时间应在很短的时间内进行,所以我不希望争夺太多。鉴于您有一位作家和多个读者,如果您的编译器最近足够,您可以尝试STD :: shared_mutex。

如果普通的静音效果太慢,您可以落回自旋锁;同样,由于应该在很短的时间内进行,因此对于您的用例来说应该很好。如果您需要更高的速度,则必须使用额外的技巧(可能使用优化的RW Spinlocks)使您的手变得肮脏。