マルチスレッドの条件変数


1.初期化条件変数pthread_cond_init

#include <pthread.h>
int pthread_cond_init(pthread_cond_t *cv,
const pthread_condattr_t *cattr);
 : 0; 

条件変数を初期化します.パラメータcattrが空のポインタの場合、関数はデフォルトの条件変数を作成します.そうでない場合、条件変数の属性はcattrの属性値によって決定されます.pthread_を呼び出すcond_init関数の場合、パラメータcattrが空のポインタはcattrの属性に等価でデフォルトの属性ですが、前者はcattrが消費するメモリオーバーヘッドを必要としません.この関数が返されると、条件変数はパラメータcvが指すメモリに格納されます.
マクロPTHREAD_を使用可能COND_INITIALIZERは、デフォルト属性を持つように静的に定義された条件変数を初期化する.これとpthread_cond_Init関数の動的割り当ての効果は同じです.初期化時にエラーチェックは行われません.次のようになります.
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;

複数のスレッドで条件変数を同時に初期化することはできません.条件変数を再初期化または解放する必要がある場合、アプリケーションはこの条件変数が使用されていないことを保証する必要があります.
 

2.条件変数のブロックpthread_cond_wait

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *cv,
pthread_mutex_t *mutex);
 : 0; 

関数はmutexパラメータが指す反発ロックを解除し、現在のスレッドをcvパラメータが指す条件変数にブロックします.
ブロックされたスレッドはpthread_cond_Signal関数、pthread_cond_broadcast関数が起動し、信号が中断された後に起動することもあります.
pthread_cond_wait関数の戻りは,条件の値が一定に変化したという意味ではなく,条件の値を再検査しなければならない.
pthread_cond_wait関数が返されると、対応する反発ロックは、関数エラーが返された場合でも、現在のスレッドによってロックされます.
一般的な条件式は、反発ロックの保護の下でチェックされます.条件式が満たされていない場合、スレッドはこの条件変数にブロックされます.別のスレッドが条件の値を変更し、条件変数に信号を送信すると、この条件変数上の1つのスレッドまたはすべてのスレッドが起動されるのを待って、対応する反発ロックを再び占有しようとする.
条件変数にブロックされたスレッドが起動された後、pthread_cond_wait()関数が返す前の条件の値が変化する可能性があります.したがって、関数が返されると、対応する反発ロックをロックする前に、条件値を再テストする必要があります.最良のテスト方法はpthread_をループ呼び出します.cond_wait関数は,条件を満たす式をループの終端条件とする.次のようになります.
pthread_mutex_lock();
while (condition_is_false)
 pthread_cond_wait();
pthread_mutex_unlock();

同じ条件変数にブロックされた異なるスレッドが解放される順序は一定ではない.
注意:pthread_cond_wait()関数は終了点であり、この関数を呼び出すと保留中の終了要求があり、スレッドが終了を許可すると、このスレッドは終了し、善後処理関数の実行を開始しますが、条件変数に関連する反発ロックはロックされます.
 

3.条件変数でのブロック解除pthread_cond_signal

#include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cv);
 : 0; 

関数は、指定した条件変数にブロックされたスレッドを解放するために使用されます.
反発ロックの保護の下で、対応する条件変数を使用する必要があります.条件変数のロック解除は、条件変数をロックする前に発生し、デッドロックを引き起こす可能性があります.
条件変数にブロックされているすべてのスレッドを起動する順序は、スレッドのスケジューリングポリシーがSCHED_である場合、スケジューリングポリシーによって決定されます.OTHERタイプの場合、システムはスレッドの優先度に基づいてスレッドを起動します.
条件変数にスレッドがブロックされていない場合はpthread_を呼び出します.cond_Signal()は機能しません.
 

4.指定時間までブロックpthread_cond_timedwait

#include <pthread.h>
#include <time.h>
int pthread_cond_timedwait(pthread_cond_t *cv,
pthread_mutex_t *mp, const structtimespec * abstime);
 : 0; 

関数は一定の時間になると,条件が発生しなくてもブロックが解除される.この時間はパラメータabstimeによって指定されます.関数が返されると、対応する反発ロックは、関数エラーが返されてもロックされることが多い.
注意:pthread_cond_timedwait関数も終了点です.
タイムアウト時間パラメータは、1日の時刻です.使用例:
pthread_timestruc_t to;
to.tv_sec = time(NULL) + TIMEOUT;
to.tv_nsec = 0;

タイムアウトで返されるエラーコードはETIMEDOUTです.
 

5.ブロックされたすべてのスレッドを解放するpthread_cond_broadcast

#include <pthread.h>
int pthread_cond_broadcast(pthread_cond_t *cv);
 : 0; 

関数はpthread_によってすべて呼び出されます.cond_wait関数はある条件変数上のスレッドをブロックし、パラメータcvはこの条件変数を指定するために使用される.スレッドがこの条件変数にブロックされていない場合、pthread_cond_broadcast関数が無効です.
pthread_cond_broadcast関数は、条件変数にブロックされているすべてのスレッドを起動します.これらのスレッドは起動すると、対応する反発ロックが再競合するため、pthread_の使用に注意する必要があります.cond_broadcast関数.
 

6.解放条件変数pthread_cond_destroy

#include <pthread.h>
int pthread_cond_destroy(pthread_cond_t *cv);
 : 0; 

条件変数を解放します.
注意:条件変数が占有するスペースは解放されません.
 

7.紛失問題の起動


スレッドが対応する反発ロックを取得していない場合にpthread_を呼び出すcond_Signalまたはpthread_cond_broadcast関数は、起動損失の問題を引き起こす可能性があります.
覚醒喪失は、次のような状況で発生することが多い.
  • スレッド呼び出しpthread_cond_Signalまたはpthread_cond_broadcast関数;
  • 別のスレッドは、テスト条件変数とpthread_を呼び出しています.cond_wait関数間;
  • スレッドがブロック待機中ではありません.