链接pthread会禁用无锁的shared_ptr实现

时间:2016-02-17 23:47:01

标签: c++ c++11 shared-ptr atomic lock-free

标题几乎传达了所有相关信息,但这里是一个最小的复制品:

#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++),在多台计算机上进行测试,这些计算机应具有必要的原子指令才能使其正常工作。

有没有办法强制实现无锁实现(我需要无锁版本,无论性能如何)?

2 个答案:

答案 0 :(得分:9)

有两件事:

  • 控制块(或等效物)中的参考计数器的操作通常使用无锁原子whenever possible来实现。这是{em>不 std::atomic_is_lock_free告诉你的内容。

    • libstdc ++的__shared_ptrtemplated 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是传递给一个帖子?你现在可以保证,但有人可能会偶然或故意将一个引入一个在不同线程中运行的东西,而且一切都会中断。