std :: atomic在一个简单的POD类上

问题描述 投票:2回答:1

我已经阅读了很多文章和问题,例如thisthisthis,所提供的所有答案都没有确定在这种情况下应该做些什么:

目前我正在编写一个并发程序,我需要同时访问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退出状态

c++ multithreading c++11
1个回答
1
投票

从评论中移动/说明:

g ++ std::atomic<T>实现requires libatomic for non-natively supported types

我可以用-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中非本机支持类型的原子存储库可以归结为either a compare-exchange loop(参见LARGER macro),或者,在“退化”情况下(T大于16字节),to a plain mutexlibat_lock_n使用目标地址的散列并锁定相应的从一些全局锁定锁定)。

这是你可以自己实现的所有东西,没有太多麻烦 - 实际上,你比libatomic的编写者处于更好的位置,因为你可以添加额外的数据成员,而不必从锁池中利用目标数据本身或其地址。

首先,我尝试使用普通的互斥锁保护您单独的数据副本。鉴于这种互斥量应该在极短的时间内使用,我不会期望有太多争用;鉴于你有一个作家和多个读者,如果你的编译器足够新,你可以尝试使用std::shared_mutex

如果普通的互斥体太慢,你可以fall back to a spinlock;再次,因为它应该在极短的时间内服用,对你的用例来说应该是完全没问题的。如果你需要更高的速度,你将不得不弄脏with extra tricks(可能使用优化的RW自旋锁)。

© www.soinside.com 2019 - 2024. All rights reserved.