TSDのいくつかの関数、pthread_key_create pthread_getspecific

2942 ワード

マルチスレッドプログラムでは、複数の関数間のデータ共有をグローバル変数で実現することがよくあります.データ空間は共有されるため、グローバル変数もすべてのプロセスに共有されます.しかし、アプリケーション設計では、スレッドにのみ有効なスレッドプライベートのグローバル変数を提供する必要がある場合がありますが、複数の関数にまたがってアクセスできます.
たとえば、プログラムでは、スレッドごとにチェーンテーブルを維持する必要があり、同じ関数を使用してこのチェーンテーブルを操作する場合、最も簡単な方法は、同じ名前で異なる変数アドレスのスレッド関連データ構造を使用することです.このようなデータ構造は、Posixスレッドライブラリによって維持され、スレッドプライベートデータ(Thread-specific Data、またはTSD)となる.
ここでは主にスレッドのプライベートデータに関する4つの関数をテストします:pthread_key_create(); pthread_key_delete(); pthread_getspecific(); pthread_setspecific(); プログラムコード:
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    pthread_key_t key;
    struct test_struct {
        int i;
        float k;
    };
    void *child1 (void*arg)
    {
        struct test_struct struct_data;
        struct_data.i=10;
        struct_data.k=3.1415;
        pthread_setspecific (key,&struct_data);
        printf ("   struct_data     0x%p
",&(struct_data)); printf ("child1 pthread_getspecific(key) :0x%p
", (structtest_struct*)pthread_getspecific(key)); printf (" pthread_getspecific(key) child1 key :
struct_data.i:%d
struct_data.k: %f
", ((structtest_struct*)pthread_getspecific (key))->i, ((structtest_struct *)pthread_getspecific(key))->k); printf ("------------------------------------------------------
"); } void *child2 (void*arg) { int temp = 20; sleep (2); printf ("child2 temp 0x%p
", &temp); pthread_setspecific (key,&temp); printf ("child2 pthread_getspecific(key) :0x%p
", (int*)pthread_getspecific(key)); printf (" pthread_getspecific(key) child2 key temp :%d
",*((int*)pthread_getspecific(key))); } int main (void) { pthread_t tid1,tid2; pthread_key_create (&key,NULL); pthread_create (&tid1,NULL, (void*)child1,NULL); pthread_create (&tid2,NULL, (void*)child2,NULL); pthread_join (tid1,NULL); pthread_join (tid2,NULL); pthread_key_delete (key); return (0); }

実行と出力:
 ./pthread_key
   struct_data     0x0xb7699388
child1   pthread_getspecific(key)      :0x0xb7699388
   pthread_getspecific(key)   child1     key          :
struct_data.i:10
struct_data.k: 3.141500
------------------------------------------------------
child2     temp      0x0xb6e9838c
child2   pthread_getspecific(key)      :0x0xb6e9838c

出力で表示、pthread_getspecific()はkeyに関連付けられたデータのポインタを返します.なお、この返されるポインタを利用する場合、まずvoidタイプであり、関連するデータアドレスを指すが、指すデータタイプが分からないため、具体的な使用時には強制タイプ変換を行う.
次に,2つのスレッドは自分のプライベートデータ操作に互いに影響を及ぼさない.つまり、keyは同名でグローバルですが、アクセスするメモリ領域は同じではありません.keyはデータ管理者のようなもので、スレッドのプライベートデータは彼のところに登録して、あなたのデータの存在を知らせます.
(PS:上記の内容もスレッドとプロセスの違い、つまりこのTSD)