linux条件変数

6146 ワード

1.関連関数
       #include
       pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
       int    pthread_cond_init(pthread_cond_t    *cond,    pthread_condattr_t
       *cond_attr);
       int pthread_cond_signal(pthread_cond_t *cond);
       int pthread_cond_broadcast(pthread_cond_t *cond);
       int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
       int   pthread_cond_timedwait(pthread_cond_t   *cond,    pthread_mutex_t
       *mutex, const struct timespec *abstime);
       int pthread_cond_destroy(pthread_cond_t *cond);
                                                                                          
2.説明
条件変数は、共有データ上のいくつかの条件が満たされるまでスレッドを停止させる同期メカニズムです.条件変数の基本的な動作は、トリガ条件(条件がtrueになった場合);待機条件、スレッドが他のスレッドにトリガーされるまで保留します.
条件変数は、条件競合を回避するために反発量と結合されます.1つのスレッドは、実際に待機に入る前に、別のスレッドが条件をトリガする条件変数を待機する準備をします.
    pthread_cond_init使用cond_attr指定属性初期化条件変数cond,cond_attrがNULLの場合、デフォルトのプロパティが使用されます.LinuxThreads実装条件変数は属性をサポートしないためcond_attrパラメータは実際に無視されます.
    pthread_cond_tタイプの変数はPTHREAD_でも使用できますCOND_INITIALIZER定数で静的初期化を行います.                                                                                          
    pthread_cond_Signalは、条件変数で待機しているスレッドの1つを再開します.待機しているスレッドがなければ、何もしません.複数のスレッドがこの条件を待っている場合、再起動できるのは1つだけですが、どちらを指定することはできません.
    pthread_cond_broadcastは、条件変数を待つすべてのスレッドを再起動します.待機しているスレッドがなければ、何もしません.
    pthread_cond_waitは、pthread_unlock_mutexが実行されるように、反発量を自動的にロック解除し、条件変数のトリガを待つ.このときスレッドは停止し、条件変数がトリガーされるまでCPU時間を消費しない.pthread_を呼び出すcond_waitの前に、アプリケーションは反発量をロックする必要があります.pthread_cond_wait関数が戻る前に、pthread_lock_mutexが実行されたように、反発量を自動的に再ロックします.
反発量のロック解除と条件変数へのサスペンションは自動的に行われる.従って、条件変数がトリガされる前に、すべてのスレッドが反発量をロックする場合、このメカニズムは、スレッドが反発量をロックし、待機条件変数に入る間、条件変数がトリガされないことを保証することができる.
    pthread_cond_timedwaitとpthread_cond_wait同様に,反発量や待機条件変数を自動的にロック解除するが,待機時間も限定する.abstimeで指定された時間内にcondがトリガーされない場合、反発量mutexは再ロックされ、pthread_cond_timedwaitはエラーETIMEDOUTを返します.abstimeパラメータは、timeとgettimeofdayと同じ絶対時間を指定します.abstime=0は1970年1月1日00:00:00 GMTを表します.
    pthread_cond_destroyは条件変数を破棄し、所有するリソースを解放します.pthread_へcond_destroyの前に、この条件変数で待機しているスレッドがない必要があります.LinuxThreadsの実装では、条件変数はリソースに結合されず、待機しているスレッドがあるかどうかを確認するほか、pthread_cond_destroyは実際には何もしません.
3.キャンセル
    pthread_cond_waitとpthread_cond_timedwaitはキャンセルポイントです.これらの関数でスレッドが一時停止されたときにキャンセルされた場合、スレッドはすぐに実行を続行し、pthread_を再度実行します.cond_waitとpthread_cond_timedwaitはmutexパラメータにロックをかけ、最後にキャンセルを実行します.したがって、パージハンドラが呼び出されると、mutexがロックされていることを確認することができる.
4.非同期信号セキュリティ(Async-signal Safety)
条件変数関数は非同期信号で安全ではなく、信号処理プログラムで呼び出すべきではない.特に、信号処理プログラムでpthread_を呼び出すとcond_Signalまたはpthread_cond_boardcast関数は、呼び出しスレッドのデッドロックを引き起こす可能性があります.
                                                                                          
5.戻り値
実行に成功すると、すべての条件変数関数は0を返し、エラー時にゼロ以外のエラーコードを返します.
6.エラーコード
    pthread_cond_init,   pthread_cond_signal,  pthread_cond_broadcast,pthread_cond_waitはエラーコードを返さない.
    pthread_cond_timedwait関数でエラーが発生した場合、次のエラーコードが返されます.
ETIMEDOUT abstime指定のタイムアウト時、条件変数がトリガーされない
        EINTR       pthread_cond_timedwaitがトリガされて中断
    pthread_cond_destroy関数でエラーが発生した場合、次のエラーコードが返されます.
EBUSYの一部のスレッドはこの条件変数を待っています
7.例
#include <stdlib.h>    
#include <stdio.h>    
#include <pthread.h>    
#include <errno.h>    
  
  
int x = 0;  
int y = 0;
  
pthread_mutex_t mutex   = PTHREAD_MUTEX_INITIALIZER;  
pthread_cond_t cond     = PTHREAD_COND_INITIALIZER;  
static void pthread_func_1 (void);     
static void pthread_func_2 (void);   



int main (void)     
{     

    pthread_t pt_1 = 0;     
    pthread_t pt_2 = 0;     
    int ret = 0;     


    pthread_mutex_init (&mutex, NULL);   
                              
    ret = pthread_create (&pt_1, NULL, (void *)pthread_func_1, NULL);
    if (ret != 0)     
    {     
        perror ("pthread_1_create");     
    }     

    ret = pthread_create (&pt_2, NULL, (void *)pthread_func_2, NULL); 
    if (ret != 0)     
    {     
        perror ("pthread_2_create");     
    }     

    pthread_join (pt_1, NULL);     
    pthread_join (pt_2, NULL);     

    printf ("x:%d, y:%d", x, y);
    printf ("main programme exit!
"); return 0; } static void pthread_func_1 (void) { printf("pthread_func_1 1111111
"); pthread_mutex_lock(&mutex); printf("pthread_func_1 22222222
"); while (x <= y) { printf("pthread_cond_wait before
"); pthread_cond_wait(&cond, &mutex); printf("pthread_cond_wait after
"); } x = 2; y = 1; printf("pthread_func_1 33333333
"); pthread_mutex_unlock(&mutex); printf("pthread_func_1 444444444
"); pthread_exit(0); } static void pthread_func_2 (void) { printf("pthread_func_2 1111111
"); pthread_mutex_lock(&mutex); x = 3; y = 2; printf("pthread_func_2 22222222
"); if (x > y) { printf("pthread_cond_broadcast before
"); pthread_cond_broadcast(&cond); printf("pthread_cond_broadcast after
"); } printf("pthread_func_2 333333333
"); pthread_mutex_unlock(&mutex); printf("pthread_func_2 444444444
"); pthread_exit (0); }

結果
pthread_func_1 1111111 pthread_func_1 22222222 pthread_cond_wait before pthread_func_2 1111111 pthread_func_2 22222222 pthread_cond_broadcast before pthread_cond_broadcast after pthread_func_2 333333333 pthread_func_2 444444444 pthread_cond_wait after pthread_func_1 33333333 pthread_func_1 444444444 x:2, y:1
main programme exit!
まとめ:前にたくさん言ったほうが、例を見て分かるように、最終的な印刷結果から見ることができます.
スレッド1:lock---判断条件---wait(ロック解除、スレッド停止、条件トリガ待ち)---条件トリガ&lock(これはwaitが自動的に実行するので、lock上で他のスレッドがunlockしているかどうかによって決まる)---後続操作---unlock
スレッド2:lock----処理x/y---条件ok,トリガ条件----unlock
したがって,条件変数とmutexを同時に用いることで,2つのスレッドの実行順序を制御できる.