【问题标题】:Linking pthread disables lock-free shared_ptr implementation链接 pthread 禁用无锁 shared_ptr 实现
【发布时间】:2016-02-17 23:47:00
【问题描述】:

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

#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++),在多台机器上进行了测试,这些机器应该有必要的原子指令来完成这项工作。

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

【问题讨论】:

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


    【解决方案1】:

    有两个不同的东西:

    • 控制块(或等效物)中引用计数器的操作通常使用无锁原子whenever possible 来实现。这不是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 告诉您shared_ptr 上的原子访问函数(std::atomic_{store, load, exchange, compare_exchange} 等)是否是无锁的。这些函数用于同时访问 same shared_ptr 对象,典型的实现将使用互斥体。

    【讨论】:

      【解决方案2】:

      如果你在线程环境中使用shared_ptr,你需要有某种锁——它们可以被实现为原子增量和减量,但是有些地方可能需要一个“更大”的锁来确保没有种族]。无锁版本仅在只有一个线程时才有效。如果您不使用线程,请不要与-lpthread 链接。

      我确信有一些棘手的方法可以让编译器相信你并没有真正将线程用于共享指针,但如果你这样做了,你真的处于脆弱的境地 - 如果 shared_ptr 被传递给一个线程?您现在可以保证这一点,但有人可能会意外或故意将其引入在不同线程中运行的东西中,这一切都会中断。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-19
        • 2023-03-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多