void undefined_behaviour_with_double_checked_locking()
{
if(!resource_ptr) #1
{
std::lock_guard<std::mutex> lk(resource_mutex); #2
if(!resource_ptr) #3
{
resource_ptr.reset(new some_resource); #4
}
}
resource_ptr->do_something(); #5
}
スレッドが別のスレッドによって書き込まれたポインターを認識した場合、新しく作成されたsome_resourceのインスタンスを認識できず、do_something()の呼び出しが誤った値で動作する可能性があります。これは、C ++標準によってデータ競合として定義され、未定義動作として指定された競合状態のタイプの例です。
質問>競合状態を引き起こすダブルチェックロックの問題がコードにある理由について、上記の説明を見ました。しかし、私はまだ問題が何であるかを理解するのに苦労しています。たぶん、具体的な2スレッドのステップバイステップのワークフローは、上記のコードの競合の問題を本当に理解するのに役立ちます。
この本で言及されている解決策の1つは次のとおりです。
std::shared_ptr<some_resource> resource_ptr;
std::once_flag resource_flag;
void init_resource()
{
resource_ptr.reset(new some_resource);
}
void foo()
{
std::call_once(resource_flag,init_resource); #1
resource_ptr->do_something();
}
#1 This initialization is called exactly once
コメントは大歓迎です-ありがとう