一个简单的POD类

时间:2017-12-26 10:40:33

标签: c++ multithreading c++11

我已经阅读了很多关于此问题的文章和问题,例如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退出状态

1 个答案:

答案 0 :(得分: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中非本机支持类型的原子存储可归结为either a compare-exchange loop(参见LARGER macro),或者在&#34;退化&#34; case(T大于16个字节),to a plain mutexlibat_lock_n使用目标地址的散列并锁定来自某个全局锁定池的相应锁定。)

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

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

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