23

別のスレッドからスレッドローカル変数を読み書きするにはどうすればよいですか? つまり、スレッド AI は、スレッド B のスレッド ローカル ストレージ領域にある変数にアクセスしたいと考えています。他のスレッドのIDはわかっています。

変数は__threadGCC と同様に宣言されます。ターゲット プラットフォームは Linux ですが、独立していると便利かもしれません (ただし、GCC 固有のものは問題ありません)。

スレッド開始フックがないため、各スレッドの開始時にこの値を単純に追跡する方法はありません。すべてのスレッドをこの方法で追跡する必要があります (特別に開始されたスレッドだけではありません)。

boost thread_local_storage や pthread キーの使用などのより高いレベルのラッパーはオプションではありません。真の__threadローカル変数を使用するパフォーマンスが必要です。


最初の答えは間違っています: 私がやりたいことにグローバル変数を使用することはできません。各スレッドには、変数の独自のコピーが必要です。さらに、これらの変数は__thread、パフォーマンス上の理由から変数でなければなりません (同様に効率的なソリューションも問題ありませんが、私は何も知りません)。また、スレッドのエントリ ポイントも制御しないため、これらのスレッドが何らかの構造を登録する可能性はありません。


Thread Local is not private : スレッドローカル変数に関する別の誤解。これらは、スレッドのプライベート変数ではありません。それらはグローバルにアドレス指定可能なメモリであり、その有効期間はスレッドに関連付けられているという制限があります。これらの変数へのポインターが与えられた場合、任意のスレッドの任意の関数が変数を変更できます。上記の質問は、基本的にそのポインターアドレスを取得する方法に関するものです。

4

4 に答える 4

17

スレッド ローカルではないスレッド ローカル変数が必要な場合は、代わりにグローバル変数を使用してみませんか?

重要な説明!

単一のグローバルを使用してスレッドローカル変数を置き換えることを提案しているわけではありません。単一のグローバル配列または他の適切な値のコレクションを使用して、1 つのスレッドローカル変数を置き換えることをお勧めします。

もちろん、同期を提供する必要がありますが、スレッド A で変更された値をスレッド B に公開したいので、それを回避することはできません。

アップデート:

上のGCCドキュメントに__threadは次のように書かれています:

address-of 演算子がスレッド ローカル変数に適用されると、実行時に評価され、その変数の現在のスレッドのインスタンスのアドレスが返されます。このようにして取得したアドレスは、どのスレッドでも使用できます。スレッドが終了すると、そのスレッド内のスレッド ローカル変数へのポインターはすべて無効になります。

したがって、この方法を主張する場合は、スレッドが生成された直後に、それが属するスレッドからスレッドローカル変数のアドレスを取得できると思います。次に、そのメモリ位置へのポインターをマップ (スレッド ID => ポインター) に格納し、他のスレッドがこの方法で変数にアクセスできるようにします。これは、生成されたスレッドのコードを所有していることを前提としています。

あなたが本当に冒険好きなら、情報を掘り下げてみることができます(前述の GCC ドキュメントによってリンクされているこの PDF___tls_get_addrから始めてください)。しかし、このアプローチは非常にコンパイラとプラットフォームに固有であり、ドキュメントが不足しているため、誰かの頭の中でアラームが鳴るはずです。

于 2011-03-15T09:38:03.810 に答える
3

残念ながら、これを行う方法を見つけることができませんでした。

ある種のスレッド初期化フックがなければ、そのポインターを取得する方法がないように見えます (プラットフォームに依存する ASM ハックを除けば)。

于 2014-06-20T10:39:34.473 に答える
0

これは古い質問ですが、答えがないので、独自の静的登録を持つクラスを使用してみませんか?

#include <mutex>
#include <thread>
#include <unordered_map>

struct foo;

static std::unordered_map<std::thread::id, foo*> foos;
static std::mutex foos_mutex;

struct foo
{
    foo()
    {
        std::lock_guard<std::mutex> lk(foos_mutex);
        foos[std::this_thread::get_id()] = this;
    }
};

static thread_local foo tls_foo;

もちろん、スレッドがポインターを登録したことを確認するには、スレッド間の何らかの同期が必要ですが、スレッドの ID を知っている任意のスレッドからマップから取得できます。

于 2021-01-05T05:23:17.287 に答える