Linking pthread disables lock-free shared_ptr implementation

我的未来我决定 提交于 2019-12-11 09:53:55

问题


The title pretty much conveys all relevant information, but here's a minimal repro:

#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);
}

Compiling this with the following compiler options produces a lock-free shared_ptr implementation:

g++ -std=c++11 -march=native main.cpp

While this doesn't:

g++ -std=c++11 -march=native -pthread main.cpp

GCC version: 5.3.0 (on Linux, using libstdc++), tested on multiple machines that should have the necessary atomic instructions to make this work.

Is there any way to force the lock-free implementation (I'd need the lock-free version, regardless of performance)?


回答1:


If you use shared_ptr in a threaded environment, you NEED to have locks [of some kind - they could be implemented as atomic increment and decrement, but there may be places where a "bigger" lock is required to ensure no races]. The lockless version only works when there is only one thread. If you are not using threads, don't link with -lpthread.

I'm sure there is some tricky way to convince the compiler that you are not REALLY using the threads for your shared pointers, but you are REALLY in fragile territory if you do - what happens if a shared_ptr is passed to a thread? You may be able to guarantee that NOW, but someone will probably accidentally or on purpose introduce one into something that runs in a different thread, and it all breaks.




回答2:


There are two separate things:

  • Manipulation of the reference counter in the control block (or equivalent thing) is typically implemented with lock-free atomics whenever possible. This is not what std::atomic_is_lock_free tells you.

    • libstdc++'s __shared_ptr is templated on the lock policy, so you can explicitly use

      template<typename T>
      using shared_ptr_unsynchronized = std::__shared_ptr<T, __gnu_cxx::_S_single>;
      

      if you know what you are doing.

  • std::atomic_is_lock_free tells you whether the atomic access functions (std::atomic_{store, load, exchange, compare_exchange} etc.) on shared_ptr are lock-free. Those functions are used to concurrently access the same shared_ptr object, and typical implementations will use a mutex.


来源:https://stackoverflow.com/questions/35470061/linking-pthread-disables-lock-free-shared-ptr-implementation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!