POSIXマルチスレッド—反発量の概要


作者:阿波リンク:http://blog.csdn.net/livelylittlefish/article/details/8096595
(半年ぶりに更新していないので、前の読書ノートをいくつか送ります.)
 
コンテント
0.シーケンス
1.基本概念
2.反発量の例
3.反発量の定義
3.1 64ビットシステム
3.2 32ビットシステム
3.3 pthread_mutext構造の内容
4.反発量の初期化と廃棄
4.1初期化
(1)静的初期化
(2)ダイナミック初期化
4.2廃棄相互反発量
5.まとめ
 
 
0.シーケンス
 
本論文のglibcバージョンは2.11で、特に説明がない場合、glibc-2.11ソースコードディレクトリを表します.本文は/usr/src/glibc-2.11です.
 
1.基本概念
 
臨界領域:共有リソースのコードセグメントにアクセスしますが、これらの共有リソースは同時に複数のスレッドにアクセスできません.つまり、共有データに影響を与えるコードセグメントです.
 
スレッド同期方法
同じ/関連データのメモリアクセスを相互にタップして行うことを保証します.つまり一回に1つのスレッドだけがデータを書くことができます.他のスレッドは待つ必要があります.Pthreadsは特殊な形式のEdsger Dijkstra信号灯を使用します.muttex:muttual(相互)、exclusion(反発); 
2.反発量の例
 
下図は、相互反発量を共有する3つのスレッドのタイミングチャートを示しています.
説明
円形の枠の上にある線分は関連スレッドが相互反発量を持っていないことを表します.円枠の中心線の上にある線分は関連スレッドの待ち時間を表します.円枠の中心線の下にある線分は関連スレッドが相互反発量を持つことを表します. 
プロセスの説明
最初、反発量はロックされていませんでした.スレッド1が互いに反発する量をロックしようとすると、競合がないため、スレッド1は直ちにロックをかけられ、対応する線分も中心線の下に移動する.その後、スレッド2はロック相互反発量を増加させようとしています.これは、スレッド2がロックされているため、対応する線分は中心線の上にあります.次に、スレッド1がロックを解除し、スレッド2がブロックを解除し、相互反発量にロックをかけることに成功する.次に、スレッド3はロック相互反発量を加えてもブロックされるようにしている.この場合、スレッド1は関数pthread_を呼び出します.mutexttrylockはロック相互反発量を加えようとしたが、すぐにEBUSYに戻る.その後、スレッド2はロックを解除し、スレッド3のブロッキングを解除し、スレッド3のロックを成功させる.最後に、スレッド3が作業を完了し、ロックを解除して互いに反発する量. 
3.反発量の定義
 
3.1 64ビットシステム
 
file:/usr/include/bits/pth readtypes.h
/* Data structures for mutex handling.  The structure of the attribute
   type is not exposed on purpose.  */
typedef union
{
  struct __pthread_mutex_s
  {
    int __lock;
    unsigned int __count;
    int __owner;
#if __WORDSIZE == 64
    unsigned int __nusers;
#endif
    /* KIND must stay at this position in the structure to maintain
       binary compatibility.  */
    int __kind;
#if __WORDSIZE == 64
    int __spins;
    __pthread_list_t __list;
# define __PTHREAD_MUTEX_HAVE_PREV      1
#else
    unsigned int __nusers;
    __extension__ union
    {
      int __spins;
      __pthread_slist_t __list;
    };
#endif
  } __data;
  char __size[__SIZEOF_PTHREAD_MUTEX_T];
  long int __align;
} pthread_mutex_t;

typedef union
{
  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
  long int __align;
} pthread_mutexattr_t;
この定義はglibcから来ています.glibcコードの位置は./nptl/sysdeps/unix/sysv/linux/x 86_です.64/bits/pth readtypes.h.64ビットのシステムは、glibcをインストールすると自動的にこのファイル(x 86 u64バージョン)をコピーします.
 
そのうち
# define __SIZEOF_PTHREAD_MUTEX_T 40
# define __SIZEOF_PTHREAD_MUTEXATTR_T 4
についてpthread_リスト.t(双方向チェーン)と_u u upthread_slist.t(一方向チェーンテーブル)の定義はソースコードを参照することができます.
 
3.2 32ビットシステム
 
file:/usr/include/bits/pth readtypes.h
/* Data structures for mutex handling.  The structure of the attribute
   type is not exposed on purpose.  */
typedef union
{
  struct __pthread_mutex_s
  {
    int __lock;
    unsigned int __count;
    int __owner;
    /* KIND must stay at this position in the structure to maintain
       binary compatibility.  */
    int __kind;
    unsigned int __nusers;
    __extension__ union
    {
      int __spins;
      __pthread_slist_t __list;
    };
  } __data;
  char __size[__SIZEOF_PTHREAD_MUTEX_T];
  long int __align;
} pthread_mutex_t;

typedef union
{
  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
  long int __align;
} pthread_mutexattr_t;
この定義はglibcから来ています.glibcコードにおける位置は./nptl/sysdeps/unix/sysv/linux/i 386/bitts/pthreadtypes.hです.32ビットのシステムはglibcをインストールすると自動的にこのファイル(i 386バージョン)を/usr/include/bitsディレクトリにコピーします.
 
そのうち
#define __SIZEOF_PTHREAD_MUTEX_T 24
#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
3.3 pthread_mutext構造の内容
 
64ビットシステムでの実験結果は以下の通りです.
(gdb) p data.mutex 
$1 = {
  __data = {
    __lock = 0, 
    __count = 0, 
    __owner = 0, 
    __nusers = 0, 
    __kind = 0, 
    __spins = 0, 
    __list = {
      __prev = 0x0, 
      __next = 0x0
    }
  }, 
  __size = '\000' , 
  __align = 0
}
4.反発量の初期化と廃棄
4.1初期化
反発量使用原則:使用前に初期化しなければならず、しかも一回だけ初期化される. 
(1)静的初期化
マクロPTHREAD_を使用しますMUTTEXINITIALIZERは、デフォルト属性の静的相互反発量を宣言する. 
file:/usr/include/pthread.h
/* Mutex initializers.  */
#if __WORDSIZE == 64
# define PTHREAD_MUTEX_INITIALIZER \
  { { 0, 0, 0, 0, 0, 0, { 0, 0 } } }
# ifdef __USE_GNU
#  define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
  { { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, { 0, 0 } } }
#  define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
  { { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, { 0, 0 } } }
#  define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
  { { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, { 0, 0 } } }
# endif
#else
# define PTHREAD_MUTEX_INITIALIZER \
  { { 0, 0, 0, 0, 0, { 0 } } }
# ifdef __USE_GNU
#  define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
  { { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, { 0 } } }
#  define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
  { { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, { 0 } } }
#  define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
  { { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, { 0 } } }
# endif
#endif
このファイルのglibcコードの位置は./nptl/sysdeps/pthread/pthread.hです.
 
 
(2)ダイナミック初期化
pthread_を通じてmutexinit()呼び出し動的初期化相互反発量;使う場合
mallocを使用して、相互反発量を含むデータ構造を動的に割り当てる場合、動的初期化を使用しなければならない.非デフォルト属性の反発量を初期化するには、動的初期化が必要です.静的な声明の相互反発量を動的に初期化することもできるが、各反発量は使用前に初期化され、一度だけ初期化されることができることを保証しなければならない. 
ダイナミックイニシャルコードは参照できます./nptl/pthread_mutexinit.そのうちpthread_mutexinit()関数は、mutexの各feildを初期化します.
 
4.2廃棄相互反発量
 
pthread_を使うmutexdestroy()は相互反発量を放出する.
 
注意
スレッドが相互反発量でブロックされておらず、相互反発量がロックされていないと確信した場合、直ちにリリースすることができる.PTHREAD_を使用して廃棄する必要はありません.MUTTEXINITIALIZERマクロの静的初期化の相互反発量. 
相互反発量コードの廃棄は参照できます./nptl/pthread_mutexdestroy.cファイル.そのうちpthread_mutexdestroy()関数は、mutexの対応するフィールドを設定して、それを利用できません.コードは以下の通りです
int
__pthread_mutex_destroy (mutex)
     pthread_mutex_t *mutex;
{
  if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
      && mutex->__data.__nusers != 0)
    return EBUSY;

  /* Set to an invalid value.  */
  mutex->__data.__kind = -1;

  return 0;
}
 
5まとめ
 
本稿では,相互反発量の基本概念を簡単に紹介し,どのように初期化し,廃棄するかという問題に注意する.後文では、加錠、解錠の原理を分析します.
 
 
Reference