クラスのメンバー変数として静的マップがあります。このマップにアクセスする必要がある場合、静的ロックが必要ですか?
4 に答える
mutex
同期された方法で使用する必要があるオブジェクトごとに 1 つだけ必要です。Joachim Isaksson が回答で示した例が示すように、1 つのオブジェクトに対して複数のミューテックスを持つと、競合状態が発生します。
static
変数にはさまざまな方法があります。
クラス静的(これはおそらくあなたが意味するものです):
class X { static map<A,B> mMap; };
システム全体で 1 つのオブジェクトしかありません。この場合、マップのミューテックスもクラス静的である必要があり、同期が必要な方法でマップが使用されるたびにロックする必要があります。クラスの静的メンバーの初期化はスレッドセーフではないことに注意してください。
関数ローカル静的:
class X { void foo() { static map<A,B> theMap{ /* ... */ }; } };
foo
それ自体がクラス static であるかどうかに関係なく、システム全体で 1 つのオブジェクトがあります。そのオブジェクトの初期化は、スレッドセーフであることが保証されています。システム全体でちょうど 1 つのミューテックスも必要です。そのミューテックスは、静的内部foo
またはクラス静的またはグローバルのいずれかである必要があります。後者の 2 つのケースでは、 を呼び出すたびにロックする必要がありますfoo
。これは、Meyers シングルトンの古典的なユースケースです。class X { static mutex mapMutex; static map<A,B>& getMap() { static map<A,B> theMap{ /* ... */ }; return theMap; } void useMap() { lock myLock(mutex); getMap()[a] = b; } };
翻訳単位静的 (「グローバル静的」)
static map<A,B> gMap; class X { /* ... */ };
そのような宣言を持つすべての翻訳単位内に 1 つのオブジェクトがあります。つまり、.cpp 内にある場合は、1 つのオブジェクトを取得します。ヘッダー内にある場合は、そのヘッダーを含む翻訳単位ごとに 1 つのオブジェクトを取得します。そのオブジェクトのミューテックスは、オブジェクトと同じ数のミューテックスが必要なため、翻訳単位も静的にする必要があります。ただし、マルチスレッド環境でその種の静的変数を使用することはお勧めしません。
いいえ、通常、静的ロックは必要ありません。