グローバルな静的変数をマルチスレッドセーフにする
-
27-09-2019 - |
質問
Cライブラリにグローバルな静的変数があり、マルチスレッド実行で例外を生成します。何らかの方法でそれらを安全にする必要があります(つまり、各スレッドはこれらの変数の異なるインスタンスに関連する必要があります)。推奨される方法はありますか?
解決
すべてのC実装で機能する標準的な方法はありませんが、実装固有のソリューションが存在します。たとえば、Microsoftのコンパイラを使用してください(参照してください ドキュメント),
__declspec( thread ) int tls_i = 1;
作る tls_i
スレッドローカルストレージに住んでいます(各スレッドには、この変数の独自のインスタンスがあります)。と GCC, 、構文はです
__thread int tls_i;
また、確認することもできます ウィキペディアエントリ 件名に。
他のヒント
最初の質問:
- スレッドには変数のコピーが必要ですか?
- または、1つの共有コピーへのアクセスを調整する必要がありますか?
前者が必要な場合、他の答えは「スレッドローカルストレージ」について提案しました。
後者が必要な場合は、どういうわけか、それらの変数に適切なミューテックスがあることを確認する必要があります(Mutexの範囲は直面する問題の1つです)。これは難しいです。変数へのアクセスを制御する関数を提供する必要があるかもしれません。
標準変数 errno
変更可能なlvalueにすることができます:
extern int *_errno_func(void);
#define errno (*(_errno_func)())
スレッドアプリケーション(-dreentrantでコンパイル)では、これが起こることです。 MacOS Xでは、とにかく起こることのように見えます(彼らは名前を使用しています __error
それ以外の _errno_func
;どちらも実装の名前空間にあります)。
変数に対して同様のことをしたい、またはしなければならない場合があります。あなたが彼らが静的であると言うという事実は、物事を少し改善します。処理するファイルは1つだけです(それらの変数へのパスバックまたはオン - ポインターを渡すのに十分な不注意でない限り)。
あなたが必要としていたのはです TLS(ローカルストレージをスレッド), 、とも呼ばれます スレッド固有のデータ また スレッドプライベートデータ. 。このメカニズムは、他のスレッドとのアクセスの同期を心配することなく、各スレッドが独自の個別のコピーにアクセスすることを保証できます。
TLSを使用する2つの方法があります。
暗黙的:キーワードの使用
ウィンドウズ: __declspec(thread)int tls_var = 10;
GCCのLinux: __thread int tls_var = 10
明示的:特定のTLS関連APIを使用します
ウィンドウズ:
- tlsalloc(): TLSデータにメモリを割り当てます
- tlsfree(): TLSデータのメモリを解放します
- tlssetValue(): TLSの値を設定します
- tlsgetValue(): TLSの値を取得します
詳細については、MSDNを参照してください。
GCCのLinux:
- pthread_key_create(): :TLSデータを作成します
- pthread_key_delete(): :TLSデータを不快にします
- pthread_getSpecific(): :TLSの値を取得します
- pthread_setspecific():TLSの値を設定します
ほとんどのコンパイラには、スレッドローカルストレージを指定する方法があります。それが利用可能であると仮定すると、それがあなたが望むものです。