web-dev-qa-db-ja.com

C ++ 11 thread_local変数は自動的に静的ですか?

これらの2つのコードセグメントに違いはありますか?

void f() {
    thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

そして

void f() {
    static thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

バックストーリー:もともと静的なベクトルV(中間値を保持するため、関数を入力するたびにクリアされます)とシングルスレッドプログラムがありました。プログラムをマルチスレッド化したいので、どういうわけかこの静的修飾子を削除する必要があります。私のアイデアは、すべての静的をthread_localに変えて、他のことを心配しないことですか?このアプローチは裏目に出ることができますか?

69
Zuza

C++標準による

Thread_localがブロックスコープの変数に適用される場合、storage-class-specifier static 暗黙的明示的に表示されない場合

つまり、この定義は

void f() {
    thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

に等しい

void f() {
    static thread_local vector<int> V;
    V.clear();
    ... // use V as a temporary variable
}

ただし、静的変数はnot thread_local変数と同じです。

1 thread_localキーワードで宣言されたすべての変数には、スレッド保存期間があります。これらのエンティティのストレージは、それらが作成されたスレッドの期間中持続します。スレッドごとに異なるオブジェクトまたは参照があり、宣言された名前の使用は、現在のスレッドに関連付けられたエンティティを参照します

これらの変数を区別するために、この標準では、静的な保存期間とともに、新しい用語thread storage durationを導入しています。

77

はい、「スレッドローカルストレージ」は「グローバル」(または「静的ストレージ」)に非常に似ていますが、「プログラム全体の期間」ではなく「スレッド全体の期間」があります。したがって、ブロックローカルスレッドローカル変数は、コントロールがその宣言を最初に通過するときに初期化されますが、各スレッド内で個別に行われ、スレッドが終了すると破棄されます。

16
Kerrek SB

thread_localと共に使用すると、staticがブロックスコープで暗黙指定され(@Vladの回答を参照)、クラスメンバーが必要になります。私は、名前空間スコープのリンケージを意味すると思います。

9.2/6あたり:

クラス定義内では、staticも宣言されていない限り、メンバーはthread_local storage-class-specifierで宣言されません。

元の質問に答えるには:

C++ 11 thread_local変数は自動的に静的ですか?

名前空間スコープ変数を除いて、選択肢はありません。

これらの2つのコードセグメントに違いはありますか?

番号。

6
vehsakul

スレッドローカルストレージは静的ですが、単純な静的ストレージとはまったく異なる動作をします。

変数を静的に宣言すると、変数のインスタンスが1つだけ存在します。コンパイラ/ランタイムシステムは、正確なタイミングを指定せずに、実際に使用する前に初期化されることを保証します(詳細はここでは省略します)。

C++ 11は、この初期化がスレッドセーフであることを保証しますが、C++ 11以前では、このスレッドセーフは保証されていませんでした。例えば

static X * pointer = new X;

複数のスレッドが同時に静的初期化コードにヒットした場合、Xのインスタンスがリークする可能性があります。

変数スレッドをローカルで宣言すると、変数のインスタンスが多数存在する可能性があります。これらは、thread-idによってインデックス付けされたマップ内にあると考えることができます。これは、各スレッドが変数の独自のコピーを見るということです。

繰り返しますが、変数が初期化されると、コンパイラ/ランタイムシステムは、データが使用される前にこの初期化が行われ、変数を使用する各スレッドで初期化が行われることを保証します。コンパイラは、開始がスレッドセーフであることも保証します。

スレッドの安全性を保証するということは、変数が期待どおりに動作するようにするための舞台裏のコードがかなりあることを意味します-特にコンパイラが正確にいくつのスレッドを知るかを事前に知る方法がないことを考慮してプログラム内に存在し、これらのうちいくつがスレッドローカル変数に触れるか。

4
Dale Wilson