スレッド局所記憶

**スレッド局所記憶**（, **TLS**）は、静的もしくは大域的なメモリをスレッドごとに局所的に使用するためのコンピュータプログラミングの方法である。

プロセス内のスレッドはすべてアドレス空間を共有しており、同じプロセスのスレッドから参照する際、静的変数やグローバル変数は同じメモリ番地に配置される。

一方スタック上の変数はすべてのスレッドが自分のスタックを持つためスレッドに対して局所的であり、異なるメモリ番地に存在する。

同じ静的変数・グローバル変数を参照する二つのスレッドが（変数をスレッドに対して局所的にすることで）実際には異なるメモリ番地を参照できることが望ましい場合がある。たとえば典型的な例としてC言語のエラーコードを格納する変数 `[[:en:errno|errno]]` がある。

少なくともメモリアドレスを格納できるサイズの変数をスレッドに対して局所的にすることが可能なら、メモリブロックを確保し、そのメモリアドレスをスレッドローカルな変数に格納すれば、原理的には任意のサイズのメモリブロックをスレッド局所にすることが可能である。

## プラットフォーム固有実装
マルチスレッドをサポートするプラットフォームや規格には、通例TLSを利用するためのAPIが用意されている。

### Windowsでの実装
Microsoft Windowsでは、Windows APIの関数 `TlsAlloc()` を用いると、未使用の**TLSスロット番号**を取得できる。これによりその番号は使用中となる。

次に`TlsGetValue()`および`TlsSetValue()`関数を用いて、番号によって識別されるスレッドローカルな変数に対する読み書きができる。`TlsSetValue()` は現在のスレッド（関数を呼び出したスレッド）の変数にしか影響を与えない。

`TlsFree()` 関数を用いると、**TLSスロット番号**を解放することができる。番号は再び未使用となり、あらたな `TlsAlloc()` により再度使用することが可能となる。

### Pthreadsでの実装
POSIXスレッド (Pthreads) では**スレッド固有データ** () と呼ばれる。このスレッド固有データは、WindowsにおけるTLSの関数や機能と同様である。`pthread_key_create()` で *key* を生成し、この *key* は`pthread_setspecific()`によって任意のデータと関連付けることができる。各 *key* に関連付けられたデータは `pthread_getspecific()` を用いて取得することができる。`pthread_key_create()`はオプションで任意の *destructor* 関数を与えることも可能であり、スレッド固有データが NULL でなければ、スレッドが終了する際 *destructor* が呼ばれる。また、*key* は `pthread_key_delete()` で破棄しなければならない。

## プログラミング言語固有の実装
プログラマが適切な API 関数を呼ぶのではなく、プログラミング言語自体が TLS をサポートするよう拡張することもできる。

### [[C言語|C]]/[[C++]]
C言語では C11 からキーワード `'''_Thread_local'''` を用いて TLS を使用できる。

C++ では C++11 においてスレッドに関する規定とキーワード `'''thread_local'''` が導入された。以下のケース全てで TLS を使用できる。
* 名前空間スコープ（グローバル）変数
* ファイルスコープ静的変数
* 関数スコープ静的変数
* 静的メンバ変数
`thread_local` を下記のように使用する:

```cpp
thread_local int number;
```

また非定数初期化子の使用やコンストラクタ・デストラクタを呼び出すクラスも使用できる。

```cpp
thread_local int number = some_non_constexpr_function();
thread_local std::vector<int> number;
```


C11/C++11 より前から以下の処理系では独自に TLS を実装している。
* Sun Studio C/C++, IBM XL C/C++, GNU C, Clang, Intel C/C++ (Linux)
*:キーワード `'''__thread'''` を下記のように使用する:
*:
```cpp
__thread int number;
```

* Microsoft Visual C++, Intel C/C++ (Windows), C++ Builder, Digital Mars C++
*:キーワード `'''__declspec(thread)'''` を下記のように使用する:
*:
```cpp
__declspec(thread) int number;
```

* C++ Builder ではキーワード `'''__thread'''` もサポートされる。
*:
```cpp
int __thread number;
```

Windows Vista および Windows Server 2008 よりも前の Windows（Windows XPなど）では、`__declspec(thread)` は実行ファイルにリンク（アーリーバインド）された DLL でのみ動作し、`LoadLibrary()` でロードされる DLL では動作しない (APIは成功を返すが TLS に関する処理が行われないため保護違反もしくはデータ破壊が発生する)。
TLS の使用にはこれ以外にもルールが存在する。Thread Local Storage (TLS) | Microsoft Docs の "Rules and limitations" を参照。

### C# および .NET 言語
静的フィールドは、ThreadStaticAttributeでマークすることができる:

```csharp
class FooBar
{
   [ThreadStatic] static int foo;
}
```

また、Thread.GetNamedDataSlot(String)メソッドによって動的にスレッド局所変数を割り当てることもできる。

### Java
Java ではスレッドローカルの変数は、クラスによって実現されている。`ThreadLocal` のオブジェクトは、オブジェクトの `get()` や `set()` メソッドをコールする各スレッドごとに、変数の異なるインスタンスを保持する。以下は、`Integer` オブジェクトを保持する`ThreadLocal` を用いた例である:


```java
ThreadLocal<Integer> local = new ThreadLocal<Integer>() {
    @Override protected Integer initialValue() {
        return 1;
    }
};
```


はじめのコードで `ThreadLocal` オブジェクト `local` を宣言、インスタンス化し、呼び出すスレッドから他の値が格納されなければ初期値 1 を返す。以下のコードは、現在の実行スレッドから値を 1 増やす。


```java
local.set(local.get() + 1);
```


`local.get()`は、現在のスレッドに関連付けられた `Integer` オブジェクトを返す。また、`local.set()` を呼び出してスレッドに関連付けた値を設定する。なお、上記の例は J2SE 5.0 で追加されたジェネリクスと自動ボックス化を使用している。

### Pascal
Object Pascal (Delphi) や Free Pascal では、`var` ではなくキーワード `threadvar` を用いてスレッド局所記憶変数を定義することができる。


```pascal
var
    myData: Integer;
threadvar
    myThreadLocalData: Integer;
```


### Perl
Perl のスレッドは言語の進化に伴って CPAN で大半のコードが利用可能になった後で追加された。

その結果、Perl では既存の非スレッドサポートのコードがスレッドのサポートにより影響を受けにくいようすべての変数をスレッドローカルとして扱うことになった。逆に Perl では、スレッドで共有される変数は attribute を用いて作成することができる。


```perl
use threads;
use threads::shared;

my $localvar;
my $sharedvar :shared;
```


### Python
Python バージョン 2.4 以降では、**threading** モジュールの **local** クラスを使ってスレッド局所記憶を作成することができる。


```python
import threading
mydata = threading.local()
mydata.x = 1
```


### Ruby
Ruby では、スレッド局所変数は []= および [] メソッドを使ってアクセスすることができる。


```ruby
Thread.current[:user_id] = 1
```


### D言語
D言語 の D2 では、グローバル変数および静的変数がデフォルトでスレッド局所変数になった。

この場合、スレッド間で共有される変数は '''shared'''修飾子もしくは '''__gshared'''属性 を用いて作成することができる。


```d
module sample;

int globalVar; // グローバル変数 (スレッド局所記憶)
shared(int) globalSharedVar; // (スレッド間共有)
```


## 外部リンク
*ELF Handling For Thread-Local Storage &mdash; C/C++ での TLS の実装についての文書
*ACE_TSS< TYPE > Class Template Reference
*RWTThreadLocal<Type> Class Template Documentation
*"Use Thread Local Storage to Pass Thread Specific Data"  Doug Doedens による記事
*"Thread-Local Storage" Lawrence Crowl による記事
*"Developer's Reference