标题几乎传达了所有相关信息,但这里是一个最小的复制品:
#include <atomic>
#include <cstdio>
#include <memory>
int main() {
auto ptr = std::make_shared<int>(0);
bool is_lockless = std::atomic_is_lock_free(&ptr);
printf("shared_ptr is lockless: %d\n", is_lockless);
}
使用以下编译器选项进行编译会产生无锁shared_ptr
实现:
g++ -std=c++11 -march=native main.cpp
虽然这不是:
g++ -std=c++11 -march=native -pthread main.cpp
GCC
版本:5.3.0
(在Linux上,使用libstdc++
),在多台计算机上进行测试,这些计算机应具有必要的原子指令才能使其正常工作。
有没有办法强制实现无锁实现(我需要无锁版本,无论性能如何)?
答案 0 :(得分:9)
有两件事:
控制块(或等效物)中的参考计数器的操作通常使用无锁原子whenever possible来实现。这是{em>不 std::atomic_is_lock_free
告诉你的内容。
libstdc ++的__shared_ptr
是templated on the lock policy,因此您可以明确使用
template<typename T>
using shared_ptr_unsynchronized = std::__shared_ptr<T, __gnu_cxx::_S_single>;
如果你知道自己在做什么。
std::atomic_is_lock_free
告诉您std::atomic_{store, load, exchange, compare_exchange}
上的原子访问函数(shared_ptr
等)是否无锁。这些函数用于同时访问相同的 shared_ptr
对象,典型的实现将使用互斥锁。 答案 1 :(得分:1)
如果在线程环境中使用shared_ptr
,你需要有某种锁[它们可以实现为原子递增和递减,但是可能存在需要“更大”锁定的地方确保没有比赛]。无锁版仅在只有一个线程时才有效。如果您不使用线程,请不要与-lpthread
链接。
我确信有一些棘手的方法来说服编译器你并没有真正使用线程作为你的共享指针,但如果你这样做的话,你真的处于脆弱的领域 - 如果shared_ptr
是传递给一个帖子?你现在可以保证,但有人可能会偶然或故意将一个引入一个在不同线程中运行的东西,而且一切都会中断。