3

マルチスレッドC++コードの一部であるオブジェクトのコンストラクターでディープコピーを実行するための最良の方法は何ですか?

4

3 に答える 3

4

データ構造に依存します。

あなたが直面している問題は (そうは言っていませんが) 潜在的なロック反転であると思います。ディープ コピーを行う場合は、コピーする必要があるさまざまなオブジェクトに対して 1 つ以上のロックを取得することになるでしょう。

ノードがシステム内のすべてのロックである DAG (つまり、半順序) を定義でき、取得する可能性のあるロックのすべての組み合わせがエッジで接続されている場合、ロックが取得されないようにすることができます。異なるスレッドで異なる順序。したがって、特にロック反転は発生しません。典型的なルールは、「最も一般的な」ロックを最後に取得することです。これは、競合を最小限に抑える傾向があるためです。

しかし、それぞれが基本的に見分けがつかない「Widgets」を含む「WidgetBoxes」全体の 1 つをディープ コピーしている場合、ボックスの内容が重複する可能性があるため、ロック順序を自然に定義するのに問題があります。さらに、最初に WidgetBox をロックする必要があります (「最も一般的な」オブジェクトであっても)。そのロックがなければ、他に何をロックする必要があるかがわからないからです。ウィジェットが同等であれば、それぞれを順番にロックし、コピーを作成して、すべてを解放できる可能性があります。汚い。

別の方法は、すべての Widget と WidgetBoxes の間で共有される単一のロックを定義することです。これにより、多くの競合が発生する可能性があります。この場合、コピーと同時に行われる変更が多すぎない限り、楽観的ロックによって問題が改善される可能性があります。

もう 1 つの方法は、コピーに関する保証を緩和することです。深い構造の識別可能な状態から完全なコピーを作成することを要求する代わりに、最初に WidgetBox をロックし、浅いコピーを行います (refcounting などを使用して - ロック)。 refcount のロックは通常「究極の内部ロック」であるため、反転のリスクはありません)、WidgetBox のロックを解除してから、各 Widget を順番にコピーします。ウィジェットに内部構造がある場合は、同じアプローチを使用してウィジェットをコピーします。結果には、別のスレッドで WidgetBox から削除されるまで達成されなかった状態の Widget が含まれる場合や、その他の不適合が含まれる場合があるため、それが受け入れられない場合は、このアプローチを使用できません。ただし、各スレッドで一度に 1 つのオブジェクトのみをロックすると、ロックの反転を取得できません。

最後の可能な「核」オプションは、すべてを不変にし、変更時に常にコピーすることです。何も変更できない場合は、ロックは必要ありません (ただし、スレッド間で参照を渡すときはメモリ バリアが必要です)。

これらのいずれも機能しない場合、私が何かを忘れていない限り、あなたは私の経験から外れています. データベースの実装は、ロックに関連する多くの巧妙さが続く場所であり、それがアイデアの対象となる領域であると推測します。

于 2008-10-06T23:56:54.010 に答える
0

フォーク()

ほんの冗談です。しかし、見逃すには面白すぎました:)

onebye は、ほとんどのオプションを網羅していると思います。おそらく、一歩下がって、そもそもディープコピーを回避する方法を見つけることができるかどうかを確認することを除いて...

于 2008-10-07T00:22:12.320 に答える
-1

私の最初の衝動 (私は専門家ではありません):

コードが書き込みに使用するオブジェクトをロックします。ディープ コピーを行う場合は、オブジェクトをロックし、ディープ コピーを実行してから、ロックを解除します。

または、ここで何か不足していますか?

于 2008-10-06T23:39:06.590 に答える