问题
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_freetells you.libstdc++'s
__shared_ptris templated on the lock policy, so you can explicitly usetemplate<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_freetells you whether the atomic access functions (std::atomic_{store, load, exchange, compare_exchange}etc.) onshared_ptrare lock-free. Those functions are used to concurrently access the sameshared_ptrobject, and typical implementations will use a mutex.
来源:https://stackoverflow.com/questions/35470061/linking-pthread-disables-lock-free-shared-ptr-implementation