GotWの記事 #45で、Herb は次のように述べています。
void String::AboutToModify(
size_t n,
bool bMarkUnshareable /* = false */
) {
if( data_->refs > 1 && data_->refs != Unshareable ) {
/* ... etc. ... */
この if 条件はスレッドセーフではありません。1 つには、"data_->refs > 1" の評価もアトミックではない可能性があります。もしそうなら、スレッド 2 が refs の値を更新している間にスレッド 1 が "data_->refs > 1" を評価しようとすると、data_->refs から読み取られた値は何か - 1、2、または何かになる可能性があります。それは元の値でも新しい値でもありません。
さらに、彼は data_->refs が 1 との比較と Unshareable との比較の間に変更される可能性があることを指摘しています。
さらに下に進むと、解決策が見つかります。
void String::AboutToModify(
size_t n,
bool bMarkUnshareable /* = false */
) {
int refs = IntAtomicGet( data_->refs );
if( refs > 1 && refs != Unshareable ) {
/* ... etc. ...*/
これで、同じ参照が両方の比較に使用され、問題 2 が解決されることがわかりました。しかし、なぜ IntAtomicGet? このトピックに関する検索では何も見つかりませんでした。すべてのアトミック操作は、読み取り、変更、書き込み操作に焦点を当てており、ここでは読み取りのみを行います。それで、私たちはただできるでしょうか...
int refs = data_->refs;
...とにかく、最終的にはおそらく1つの命令に過ぎないのでしょうか?