Linuxマルチスレッド-条件変数

9204 ワード

http://www.cnblogs.com/feisky/archive/2010/03/08/1680950.html

条件変数の概要
反発ロックとは異なり、条件変数はロックではなく待つために使用されます.条件変数は、特定の状況が発生するまでスレッドを自動的にブロックするために使用されます.通常、条件変数と反発ロックは同時に使用されます.
条件変数は、ある条件が現れるのを待つために睡眠をとることができます.条件変数はスレッド間で共有されるグローバル変数を利用して同期するメカニズムであり、主に2つの動作を含む:1つのスレッドが「条件変数の条件が成立する」ことを待って保留する;もう1つのスレッドは「条件成立」(条件成立信号を与える)を使用する.
条件の検出は,反発ロックの保護下で行った.条件が偽の場合、スレッドは自動的にブロックされ、待機状態が変化する反発ロックが解放されます.別のスレッドが条件を変更すると、関連する条件変数に信号を送り、1つ以上の待機スレッドを呼び出し、反発ロックを再取得し、条件を再評価します.2つのプロセスが読み書き可能なメモリを共有する場合、条件変数を使用して、2つのプロセス間のスレッド同期を実現できます.
条件変数を使用する前に初期化を行います.プロセス間スレッドの通信のためのpthread_cond_t my_condition=PTHREAD_COND_INITIALIZER;などの条件変数を単一の文で生成および初期化できます.関数pthread_を使用できますcond_Initダイナミック初期化.
条件変数は2つの部分に分けられる:条件と変数.条件自体は反発量によって保護される.スレッドは条件状態を変える前に反発量をロックしなければならない.それはスレッド間で共有するグローバル変数を利用して同期するメカニズムである.
関連する関数
次のようになります.
int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);    
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);
int pthread_cond_destroy(pthread_cond_t *cond);  
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);  //         

簡単な説明:
  (1)   .init()  `pthread_cond_t cond=PTHREAD_COND_INITIALIER;`    NULL

  (2)      .pthread_wait,pthread_timewait.wait()   ,           

  timewait()      ,  signal,  `ETIMEOUT`(          wait)

  (3)      :`pthread_cond_signal`,`pthread_cond_broadcast`(        )

  (4)      :`destroy`;     ,    `EBUSY`

詳細な説明
1.初期化:
条件変数に用いるデータ型は、pthread_cond_t,を使用する前に初期化しなければならない.•静的:定数PTHREAD_COND_INITIALIZERを静的に割り当てることができる条件変数.•動的:pthread_cond_init関数は、動的条件変数のメモリ空間を解放する前に、pthread_cond_destroyでクリーンアップする.
#include <pthread.h>

int pthread_cond_init(pthread_cond_t *restrict cond, pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);

成功すると0を返し、エラーが発生するとエラー番号を返す.pthread_cond_initのattrパラメータがNULLの場合、デフォルト属性の条件変数が作成されます.デフォルトでない場合は後で議論する.
2.待機条件:
#include <pthread.h>

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restric mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout);

成功すると0を返し、エラーが発生するとエラー番号を返す.
この2つの関数はそれぞれブロック待ちとタイムアウト待ちである.待ち条件関数待ち条件が真となり,pthread_cond_waitに伝達される反発量が条件を保護し,呼び出し者はロックされた反発量を関数に伝達する.関数は呼び出しスレッドを待ち条件のスレッドリストに配置し,反発量をロック解除する.この2つの動作は原子的である.これにより条件検査とスレッドがスリープ状態に入る待機条件が変化する2つの動作間の時間チャネルが閉じられ,スレッドが条件の変化を逃すことがない.pthread_cond_waitが戻ると、反発量は再びロック.
3.通知条件:
#include <pthread.h>

int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);


成功すると0を返し、エラーが発生するとエラー番号を返す.
                 .        ,             .     ,                     .

条件変数と反発ロック、信号量の違い
   1.                 ,                          。               ,              。

   2.       ,     (    ,       )。

   3.               (     ),            。               ,               ,        。

   4.            ,             ,         ,      ,                  。

単純なプログラムインスタンス
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>

pthread_mutex_t m_lock;//   
pthread_cond_t cond;//    

void thread_clean(void *arg)
{
    pthread_mutex_unlock(&m_lock);//         -->   
}

void *my_fun1(void *arg)
{
    thread_cleanup_push(thread_clean, NULL);
    while(1){
        printf("my_fun1 is running
"
)
; pthread_mutex_lock(&m_lock); pthread_cond_wait(&cond, &m_lock); printf("func 1 cond worked
"
)
; pthread_mutex_unlock(&m_lock); sleep(2); } pthread_cleanup_pop(0);// --> return NULL; } void *my_fun2(void *arg) { while(1){ sleep(2); printf("my_fun2 is running
"
)
; pthread_mutex_lock(&m_lock); pthread_cond_wait(&cond, &m_lock);// , printf("func 2 cond worked
"
)
; pthread_mutex_unlock(&m_lock); sleep(1); } return NULL; } int main() { pthread_t tid1, tid2; printf("hey, this is main
"
)
; pthread_mutex_init(&m_lock, NULL); pthread_cond_init(&cond, NULL); pthread_create(&tid1, NULL, my_fun1, NULL); pthread_create(&tid2, NULL, my_fun2, NULL); while(1){ pthread_cancel(tid1);// tid1 sleep(2); pthread_cond_signal(&cond);// , , } sleep(1); return 0; }

実行結果:
yu@ubuntu:~/Linux/201$ ./10tiaojianval
hey, this is main
my_fun1 is running
my_fun2 is running
func 2 cond worked
my_fun2 is running
func 2 cond worked
my_fun2 is running
func 2 cond worked
my_fun2 is running
^C