5

pthread dataspecific がどのように機能するかはわかりません。次のコード (Web で見つかります) を考慮すると、これは、たとえばメインで 5 つのスレッドを作成し、それらの一部だけで func を呼び出すことができることを意味します (2 としましょう) ) これらのスレッドは、データの「キー」を何かに設定し (ptr = malloc(OBJECT_SIZE) )、他のスレッドには同じキーが存在しますが、NULL 値がありますか?

static pthread_key_t key;
static pthread_once_t key_once = PTHREAD_ONCE_INIT;

static void
make_key()
{
  (void) pthread_key_create(&key, NULL);
}

func()
{
  void *ptr;

  (void) pthread_once(&key_once, make_key);
  if ((ptr = pthread_getspecific(key)) == NULL) {
    ptr = malloc(OBJECT_SIZE);
    ...
    (void) pthread_setspecific(key, ptr);
  }
  ...
}

dataspecific がどのように機能するか、および pthread でどのように実装されているか (簡単な方法) についての説明をいただければ幸いです。

4

2 に答える 2

7

あなたの推論は正しいです。これらの呼び出しは、スレッド固有のデータに対するものです。これらは、各スレッドに、必要なものを格納できる「グローバル」領域を提供する方法ですが、必要な場合に限ります。

キーは最初に必要になったときに作成されるため、すべてのスレッドで共有されますpthread_once()が、そのキーに与えられる値はスレッドごとに異なります(NULLに設定されたままの場合を除く)。値avoid*をメモリブロックに設定することにより、スレッド固有のデータを必要とするスレッドは、値を割り当てて、後で使用するためにアドレスを保存できます。また、スレッド固有のデータを必要とするルーチンを呼び出さないスレッドは、割り当てられないため、メモリを浪費することはありません。

私がそれらを使用した1つの領域は、標準Cライブラリをスレッドセーフにすることです。私が関わった実装のstrtok()関数(スレッドセーフとは対照的にstrtok_r())は、最初に呼び出されたときにほぼ同じコードを使用して、によって使用されるメモリを割り当てました。strtok()後続の呼び出しのために情報を保存するため。これらの後続の呼び出しは、スレッド固有のデータを取得して、まったく同じことを行う他のスレッドに干渉することなく、文字列のトークン化を続行します。

つまり、ライブラリのユーザーはスレッド間のクロストークについて心配する必要がありませんでした。最後のスレッドが終了するまで、単一のスレッドが関数を呼び出さないようにする必要がありましたが、これはシングルスレッドコードの場合と同じです。

これにより、他のベンダーがユーザーに課す通常の「これらの特別な非標準の再入可能ルーチンを呼び出す必要がある」という制限なしに、システムで実行されている各スレッドに「適切な」C環境を与えることができました。

実装に関しては、DCEユーザーモードスレッド(現在のpthreadの前身だと思います)について覚えていることから、各スレッドは、命令ポインター、スタックポインター、レジスターの内容などを格納する単一の構造を持っていました。最小限のコストで非常に強力な機能を実現するために、この構造に1つのポインターを追加することは非常に簡単なことでした。ポインターは、キーとポインターのペアの配列(一部の実装ではリンクリスト)を指しているため、各スレッドは複数のキー(たとえば、1つはstrtok()、1つはrand())を持つことができます。

于 2009-02-14T12:38:37.267 に答える