SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

pthreadについて

pthreadについて(スレッド固有データ)

スレッド単体で管理できる情報の生成・管理方法


  • X ポスト
  • このエントリーをはてなブックマークに追加

7. スレッド固有データ(Thread Specific Data:TSD)

 スレッドはあくまでプロセスの一部である事は既に述べました。スレッドはプロセスとさまざまな情報が共有されています。1章でも述べましたが、スレッドが独立で管理できる情報、つまりスレッド固有なデータは下記のみです。

  • スタック
  • スレッドID ( pthread_t
  • シグナルマスク ( pthread_sigmask(3)) ※ signalについて 参照
  • 代替シグナルスタック ( sigaltstack(2)) ※ signalについて 参照
  • errno変数
  • スケジューリングのポリシーと優先度 ※ 別章参照

 上記以外の情報、例えばプロセスIDなどの各種IDやグローバルなデータはプロセス共有となっています。

 しかし、スレッドが使用できるメモリがスタックだけでは都合が悪い時もあります。例えばスレッド内から呼ばれる関数でエラー情報をグローバルな変数にセットする場合、その変数はスレッド固有でないと、エラー情報が上書かれてしまうなどの弊害が発生します。

 上記以外でスレッド固有なデータを取得するには別途方法があります。特にグローバルな変数に対して完全にスレッド固有な、スレッドにとってプライベートな領域を確保する方法について述べていきます。

7.1 リファレンス

 主にスレッド固有データの生成にかかわる関数は下記の通りです。より詳細についてはmanコマンド、もしくはココを参照してください。

  • int pthread_key_create( pthread_key_t * key, void ( *destr_function )( void * ));
  • スレッド固有データキーを初期化します。
    • pthread_key_t:スレッド固有データキー。このキーに対してスレッド固有情報を取得します。1回だけpthread_key_createを実行する必要があります。通常、pthread_onceを利用します。
    • destr_function:いわゆるデストラクタです。使用しない場合はNULLでも良いです。主な使用法は8.3で説明します。
  • int pthread_key_delete( pthread_key_t key );
  • スレッド固有データキーを削除します。
  • int pthread_setspecific( pthread_key_t key, const void * pointer );
  • スレッド固有データキーに対し、pointerの値を結びつけて管理します。つまりpointerの値をスレッド固有データにします。
  • void * pthread_getspecific( pthread_key_t key );
  • スレッド固有データキーが管理している値を取得します。戻り値がNULLの時は登録されていないので、その際はpthread_setspecificを使って登録します。

7.2 プログラム

 まず下記のサンプルを実行してください。

tsd_once.c 実行結果
guest $ ./tsd_once
pthread_getspecific is NULL!!
[thread 1] set tsd value 0x81be560
[thread 1] starting...
[thread 2] set tsd value 0x81be560
[thread 2] starting...
[thread 3] set tsd value 0x81be560
[thread 3] starting...
thread 3 done...
thread 3 done...
thread 3 done...
guest $

 実行すると3つのスレッドの情報が出力されますが、同じアドレスを参照している事が分かります。参照しているアドレスはグローバルな変数で、各スレッドが書き込みや参照をしています。最後にスレッドが終了する際に出力される情報は、最後に動いたスレッドによって上書かれている事が分かります。

 次のサンプルを試してみてください。

tsd_once_2nd.c 実行結果
guest $ ./tsd_once_2nd
initializing key
pthread_getspecific is NULL!!
[thread 1] set tsd value 0x9550560
[thread 1] starting...
pthread_getspecific is NULL!!
[thread 2] set tsd value 0x9550570
[thread 2] starting...
pthread_getspecific is NULL!!
[thread 3] set tsd value 0x9550580
[thread 3] starting...
thread 1 done...
thread 2 done...
thread 3 done...
guest $

 同様に実行すると、先ほどとは違って上書きされておらず固有のデータとして扱われているのが分かります。参照しているアドレスは先ほどと同じグローバルな変数で、各スレッドが書き込みや参照をしています。

 もう1つ、次のサンプルを試してみてください。

tsd_once_3rd.c 実行結果
guest $ ./tsd_once_3rd
pthread_getspecific is NULL!!
[thread 1] set tsd value 0x8969578
[thread 1] starting...
pthread_getspecific is NULL!!
[thread 2] set tsd value 0x8969588
[thread 2] starting...
pthread_getspecific is NULL!!
[thread 3] set tsd value 0x8969598
[thread 3] starting...
thread 1 done...
thread 2 done...
thread 3 done...
guest $

 これも同様に固有のデータとして扱われているのが分かります。このサンプルはtsd_once.cとほとんど同じで、一点だけ__threadキーワードが付加されいるだけです(動かない場合は環境が新しくないという事になります)。

guest $ diff tsd_once.c tsd_once_3rd.c
2,3c2,3
< gcc tsd_once.c -o tsd_once -W -Wall -g -lpthread
<  */
---
> gcc tsd_once_3rd.c -o tsd_once_3rd -W -Wall -g -lpthread
> */
13c13
< tsd_t * value = 0;
---
> __thread tsd_t * value = 0;
guest $

 __threadキーワードについては後述します。

次のページ
7. デストラクタ

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
pthreadについて連載記事一覧

もっと読む

この記事の著者

赤松 エイト(エイト)

(株)DTSに勤てます。WebアプリやJavaやLL等の上位アプリ環境を密かに憧れつつも、ず~っとLinuxとかHP-UXばかり、ここ数年はカーネル以上アプリ未満のあたりを行ったり来たりしています。mixiもやってまして、こちらは子育てとか日々の日記メインです。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/1969 2008/08/20 16:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング