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