2

私はレガシーC/C ++コードのコードベースを持っています。これには、グローバル静的変数にアクセスする多くの関数が含まれているため、スレッドセーフではありません。このコードをスレッドセーフにする方法についてのアドバイスを探しています。そのための1つの方法は、静的変数をスレッドローカル変数に変換するか、スレッドローカルストレージに格納することです。これには、関数を使用して追加のコンテキストを渡すコードをたくさん書き直す必要がなく、スレッドセーフでない関数自体だけを書き直す必要がないという利点があります。しかし、これを調査したところ、これが良いアイデアか悪いアイデアかについてのアドバイスはあまり見つかりませんでした。私が持っているいくつかの特定の懸念は

  • TLSベースのデータへのアクセスは大幅に遅くなりますか?
  • am I just continuing to fall into the trap of using global variables, since "global variables are bad", or does TLS counteract the global-variables-are-bad argument?

Any other thoughts would be appreciated too.

4

6 に答える 6

2

まず第一に、どのグローバル変数が変更可能な方法でアクセスされ、どのグローバル変数がそうでないかを判断するのが最善です。変数が一度設定されると実際には変更されない場合がいくつかありますが、それらの変数の初期化が非決定論的プログラムに問題を引き起こすだけです。初期化の順序が重要になるこれらの変数は、それらを必要とする個々のスレッドに伝播できる独自のクラスに配置します。

その後、あなたの問題は悪化するだけだと確信しています。私はあなたがいる場所にいて、同情しています。

于 2010-09-13T14:54:48.493 に答える
1

TLS を使用する際の問題は、クライアントにスレッド アフィニティを強制することです。クライアントはこれを認識し、それに応じて処理するコードを作成する必要があります。そのため、重い作業を行うワーカー スレッドがある場合は、ライブラリへのすべての呼び出しを、単純なゲッターとセッターであっても、そのワーカー スレッドにマーシャリングする必要があります。または、他のコンポーネントがスレッド プール スレッド上のコンポーネントを呼び出す場合 (たとえば)、その呼び出しをワーカー スレッドにマーシャリングする必要があります。世界で最悪というわけではありませんが、非常に不便な場合があります。私は間違いなくハンドル/コンテキスト パターンを好みます (私は TLS を使用するライブラリを維持していますが、スレッド アフィニティを扱うのは面倒な作業でした)。

于 2010-09-13T15:22:02.090 に答える
0

変換する予定のすべての変数のセマンティクスを理解していない場合、グローバルから TLS への変換を単純に自動化するだけでは、非常に非生産的なタイムシンクになる可能性があります。それらのいくつかは、グローバルのままでスレッドセーフな方法で処理する必要があるかもしれません.TLSとして使用するのが非常に安全かもしれません. さらに、TLS のようにスレッドセーフな場合もありますが、スレッドの数を増やすと、スケーラブルではない不適切な設計になります (たとえば、以前はシングルクライアントでシングルスレッドのソケット サーバーでは、クライアント/スレッドごとに 1 つのソケットがありました)。

ここで選択したプラットフォーム/コンパイラは何ですか?

于 2010-09-13T15:17:19.317 に答える
0

すべての変数をスレッド ローカル ストレージに格納するよりも、変数をクラスに格納する方がよいと思います。元のコードの大部分が C である場合、C コードをクラスにラップして、「グローバル」変数をフィールドとして持つことができる場合があります。異なるスレッドで実行されているクラスの異なるインスタンスは、当然これらの変数の異なるバージョンを参照します。

于 2010-09-13T15:26:59.490 に答える
0

正確さに関しては、スレッド化が競合を引き起こす可能性のある他の意味を持たない限り、これが機能しない理由はわかりません。すべてのグローバルをキャッチして変換したことを確認する必要があります。

大幅に遅いかどうかを判断する最善の方法は、コードの変換されたセクションをプロファイリングして確認することです。

そうは言っても、これが最善の解決策であるかどうかはわかりません。グローバル変数は、その名前に関係なく、まさにそれであり、プログラムの状態の追跡とデバッグを完全な悪夢にします。コードをよく見て、グローバルに依存しないスレッドセーフなコードに一度に 1 つずつリファクタリングすることを真剣に提案します。デバッグがはるかに簡単になり、将来のメンテナー (またはあなた自身) は今から数年後にあなたに感謝するでしょう.

于 2010-09-13T15:15:17.027 に答える
0

まあ、そこから始めるのはかなり簡単でしょう。スレッドローカルの条件付きコンパイルを行うことができます。Visual Studio などの一部のコンパイラには、ドロップインできる独自の thread_local ストレージがあります。

于 2010-09-13T15:06:03.177 に答える