スレッドローカルストレージ
読み:スレッドローカルストレージ
外語:TLS: Thread local storage
スレッドごとに持っている局所記憶。
概要
同じプロセスは同じメモリー空間を共有している。
スタックはスレッドごとに異なるためスタックに記憶される変数は局所的となるものの、同じプロセスであれば異なるスレッドであっても同じ静的変数やグローバル変数が参照できる。
しかし、同じ変数でもスレッドごとに一意でなければ困るものもある(例えばerrno変数など)。
このような用途のため、スレッドごとに用意される局所的な領域を、スレッドローカルストレージという。
特徴
利用方法
マルチスレッドオペレーティングシステムではほぼ例外なく用意しているが、ユーザーが利用する場合の手法は、オペレーティングシステム(OS)ごとに様々である。
また、OSではなく、言語が独自に用意する場合もある。
Microsoft Windows
TlsAlloc関数でTLSインデックスを取得し、TlsSetValue関数/TlsGetValue関数を用いて読み書きをする。
使用後は、TlsFree関数を使って解放する。
POSIXスレッド
POSIXスレッドにおいても、利用方法はほぼ同じである。
pthread_key_create関数でスレッド固有データキーを作成する。pthread_setspecific関数/pthread_getspecific関数で、スレッド固有データをキーに関連付けたり、関連付けられたスレッド固有データを取得したりできる。
使用後は、pthread_key_delete関数を使ってスレッド固有データキーを削除する。
情報のありか
スレッドごとの固有の情報がどこにあるかは、その実装ごとに様々である。
Windowsであれば、各スレッドごとの情報を管理するTIB(Thread Information Block)に格納される。
プログラミング言語
プログラミング言語によっては、システムコールを呼ばなくても言語仕様としてTLSに変数を宣言することができる。
Delphi
Delphiでは、varではなく、threadvarで変数を宣言することで、スレッドローカル変数を使うことができる。
var
number_process: integer;
threadvar
number_tls: integer;
Delphi互換のFree Pascalも同様。
Java
Javaは、J2SE 1.2以降でThreadLocalクラスが導入された。
ThreadLocalクラスをインスタンス化し、set/getメソッドで設定または取得をする。
C/C++
C/C++の従来の仕様では対応していないため、処理系が独自に実装していた。
正式対応と追加された予約語は、次のとおりである。
追加された予約語を変数宣言時に用いることで、スレッドローカル変数を宣言できるようになった。
Visual C++
__declspec(thread)を使用することで利用できる。
__declspec(thread) int val;
Windows 7以降でないとLoadLibrary()で呼ぶDLLには利用できないなど、様々な制限が存在する。
GCC
__thread を使用することで利用できる。
__thread int val;
この変数はグローバル変数または関数内の静的変数として定義される必要があり、関数内の自動変数(auto変数)としては使用できない。
例ではint型だが、データ型はint以外でも、構造体でも利用できる。またint等と__threadの記述順序は問わない。但し静的変数にする場合は、staticは__threadより前に書かねばならない。
加えて、静的変数として定義する場合、宣言時に定数は代入できても変数を代入することは出来ない。これは言語仕様であり__threadを使わなくても同様である。
void hoge(int i)
{
static __thread int v1 = 0; /* OK */
static __thread int v2 = i; /* ERROR */
v1 = i; /* OK */
}
後から代入する分には問題はない。
Borland C++ Builder
Borland C++ Builderでは、Visual C++スタイルの__declspec(thread)も、GCCスタイルの__threadも利用できる。
再検索