std::shared_ptrのスレッド間コピーはスレッドセーフ

C++11標準ライブラリのスレッド安全性

オブジェクトがスレッド間共有される内部状態を持つ場合でも、データ競合が生じないことを保証する。例:スレッド毎のstd::shared_ptrオブジェクトが同一オブジェクトを指しているとしても、各スレッド上で行われるstd::shared_ptrオブジェクト操作を安全に行える。[7](17.6.5.9/p7)

[7]:例えばstd::shared_ptrが参照カウンタ方式で内部実装されていた場合、処理系はその参照カウンタ更新をデータ競合なしに行う義務がある。

std::shared_ptrの参照カウンタはアトミックであることが義務付けられている、という話は前から知っていたものの、どこに書いてあるのかわからず悩んでましたが、id:yohhoy先生がすでに調べてくれてました。


これの経緯としては、N2351 Improving shared_ptr for C++0x, Revision 2にて、「A variant of shared_ptr that is atomic, that is, safe to be manipulated from multiple threads without synchronization; (shared_ptrはアトミックであり、同期を使うことなく複数スレッドから安全に操作できる)」ということで入ったようです。


GCCのstd::shared_ptrの内部実装にアトミックが使われるようになったのは、以下のメールでのパッチ。
Tweaking atomics and memory barriers in shared_ptr


それと、std::shared_ptrはなぜアトミックバージョンのみを提供しているのか、という質問が以下。
Is there a non-atomic equivalent of std::shared_ptr? And why isn't there one in <memory>?
アトミックでの参照カウントは、当然ながら単なるintでの加算・減算に比べたコストは、ゼロではありません。ですが、ムーブを活用することでコストを低減することはできる。ということのようです。


ちなみにBoostでは、BOOST_SP_DISABLE_THREADSを定義して無効にしない限りは、shared_ptrの参照カウントがアトミックになります。