2010-11-30 23 views
5

数ヶ月前に、私は男(orkut)のこの面白いシナリオを尋ねました。しかし、私はこの問題(小さなコードでテストしたことがあります)に「移植性のない」ソリューションを考え出しましたが、依然として皆さんが何を言い、示唆しているかを知りたいと思います。シナリオ:マルチスレッドアプリケーションで使用されているDLLのグローバル変数

私はDLLを作成して、C++で書かれたいくつかの機能をエクスポートしました。はシングルスレッドクライアントです。このDLLは大量のグローバル変数を宣言しています。いくつかの変数はconst変数(読み取り専用)であり、その他は変更可能です。

とにかく、後のことが変わったので、同じDLLをマルチスレッドアプリケーション(DLLを変更せずに)で動作させたい。つまり、いくつかのスレッドがDLLから関数とグローバル変数にアクセスし、それらを変更します。これらはすべて、グローバル変数に一貫性のない値を保持させる可能性があります。

そこで質問が

たちはDLLのマルチアクセスを防止するために、クライアントコードで何かを行うことができ、同時に、が各スレッドはそれ自身のコンテキスト(つまり、で実行されることを確実にすること、ですDLLにアクセスすると、DLLのグローバル値は以前と同じになります)。

+0

dllを少なくとも再構築することが許可されている場合は、すべてのグローバル定義に__declspec(threadlocal)を追加できます。コンストラクタやデストラクタを持つ静的スコープのクラスオブジェクトでは失敗すると強く思っています。 –

+0

Chris ...いいえ、ソースコードの変更が許可されていないため、__declspec(threadlocal)をグローバルに追加できません。 :-) – Nawaz

答えて

1

DLLのマルチアクセスを防止すると同時に、各スレッドが独自のコンテキストで実行されるようにすることもできます(つまり、DLLにアクセスすると、 DLLのグローバル値はこれまでと同じです)?

これは難しい部分です。私はこれを行う唯一の方法は、既存のDLLの周りにラッパーを作成することだと思う。呼び出されると、現在のスレッドの状態(グローバル変数)が復元され、DLLへの呼び出しが返ったときに保存されます。 DLL内のすべての状態変数を知り、それらを読み書きできるようにする必要があります。

パフォーマンスに問題がない場合は、DLL全体に対して単一のロックで十分であり、正しく実装するのが最も簡単です。これにより、一度に1つのスレッドのみがDLLにアクセス(読み取りまたは書き込み)していることが保証されます。

2

もちろん、ロックなどのマルチスレッド固有のタスクを処理するラッパーレイヤーを常に作成できます。元のDLLとリンクしている2番目のDLLで実行して、その新しいDLLとの最終的なプロジェクトリンクを作成することもできます。

どのように実装しても、これは簡単な作業ではありません。デッドロックや競合状態のような問題に遭遇しない限り、どのスレッドがいつ何時にどの値を変更でき、誰がいつ何かを読むことができるかを正確に知る必要があります。

解決策があれば、データを変更するスレッドを1つ割り当て、他のすべてのスレッドを読み書きしないようにしてください。同時読み込みアクセスは同時書き込みアクセスよりも実装が容易です(Boostこれを行うためのすべての基本機能を提供します(例:shared_mutex)。

+0

Mephane、あなたの最後の段落は意味があり、実際に私のソリューションではBoost APIを使用せずに同様のことをしました。 途中であなたの応答に感謝します。 :-) – Nawaz

+0

ところで、グローバル変数の値は、スレッドごとに異なる可能性が高いと認識していますか?そのため、あるスレッドが(他のスレッドのロック中に)DLLにアクセスするたびに、以前と同じように、この現在のスレッドは同じポイント/ステートから実行されなければならないことを意味します。 – Nawaz

+0

申し訳ありませんが、前のコメントで説明したように、Boost APIがケース(異なるスレッドやすべての値が異なる)を処理するのですか? – Nawaz

関連する問題