2016-02-17 4 views
1

Названные в значительной степени передает всю необходимую информацию, но вот минимальная репродукция:Соединения нитей отключают безблокировочный реализация shared_ptr

#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++), протестирована на нескольких машинах, которые должны иметь необходимые атомарные инструкции для выполнения этой работы.

Есть ли способ принудительно реализовать блокировку (мне нужна бесплатная версия, независимо от производительности)?

ответ

1

Если вы используете shared_ptr в поточной среде, вам НЕОБХОДИМО иметь блокировки [своего рода - они могут быть реализованы как атомные приращения и уменьшения, но могут быть места, где требуется «большая» блокировка, чтобы не было никаких гонок ]. Бесключевая версия работает только тогда, когда есть только один поток. Если вы не используете потоки, не связывайтесь с -lpthread.

Я уверен, что есть какой-то сложный способ убедить компилятор, что вы НЕ ДЕЙСТВИТЕЛЬНО используете потоки для ваших общих указателей, но вы ДЕЙСТВИТЕЛЬНО на хрупкой территории, если вы это сделаете - что произойдет, если shared_ptr передается нить? Вы можете быть в состоянии гарантировать, что СЕЙЧАС, но кто-то, вероятно, случайно или намеренно вводит его во что-то, что работает в другом потоке, и все это ломается.

7

Есть две разных вещи:

  • манипуляционных опорный счетчика в блоке управления (или эквивалент) вещи обычно реализуются с безблокировочным Атомиксом whenever possible. Это не, что и std::atomic_is_lock_free.

    • libstdC++ 's __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, а в типичных реализациях будет использоваться мьютекс.