[C/C++]_[初級][スレッドpthread学習の反発ロックと条件変数の応用]


一、反発ロック反発ロックは、信号量であり、2つのプロセスまたはスレッドが同じ時点で同じ共有リソースにアクセスすることを防止するためによく用いられる.必要なヘッダファイル:pthread.h反発ロック識別子:pthread_mutex_t(1)反発ロック初期化:関数プロトタイプ:int pthread_mutex_init(pthread_mutex_t*mutex,const pthread_mutexattr_t*mutexattr);関数入力値:mutex:反発ロック.mutexattr:PTHREAD_MUTEX_INITIALIZER高速反発ロックを作成します.PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NPは再帰的反発ロックを作成する.PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NPは誤り検出相互反発ロックを作成する.関数の戻り値:成功:0;エラー:-1(2)反発操作関数int pthread_mutex_lock(pthread_mutex_t*mutex);//鍵をかけるmutex_trylock (pthread_mutex_t* mutex);//反発がロックされている場合にのみint pthread_がブロックされます.mutex_unlock (pthread_mutex_t* mutex);//解錠int pthread_mutex_destroy (pthread_mutex_t* mutex);//反発ロック関数の入力値をクリアします:mutex:反発ロック.関数の戻り値:成功:0;エラー:-1使用形式:pthread_mutex_t mutex; pthread_mutex_init (&mutex, NULL);/*定義*/...pthread_mutex_lock(&mutex);/*反発ロックの取得*/.../*臨界リソース*/pthread_mutex_unlock(&mutex);/*反発ロックを解除*/スレッドが反発量にロックされ、操作中にロックされた操作が再び呼び出されると、スレッドは無限にこの場所にブロックされ、デッドロックを引き起こす.これには反発量の属性が必要です.反発量は以下の3種類に分けられる:1、高速型.このタイプもデフォルトのタイプです.このスレッドの動作は前述したとおりです.2、再帰型.上記のデッドロック状況に遭遇し、同じスレッドが反発量にループしてロックされると、システムは、ロック動作が同じスレッドから来ていることを認識し、スレッドが反発量にロックされることに同意します.3、エラー検出タイプ.反発量がロックされている場合、後続のロックはブロックされずに失敗します.pthread_mutex_lock()操作はEDEADLKを返します.反発量の属性タイプはpthread_mutexattr_t.宣言後にpthread_を呼び出すmutexattr_Init()を使用して、反発量を作成します.pthread_を呼び出しますmutexattr_settypeでプロパティを設定します.フォーマットは次のとおりです:int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind); 最初のパラメータattrは、前に宣言した属性変数です.2番目のパラメータkindは、設定するプロパティタイプです.彼には次の選択肢があります.PTHREAD_MUTEX_FAST_NP PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_ERRORCHECK_NPでは、プロパティを使用する簡単な手順を示します.pthread_mutex_t mutex; pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE_NP); pthread_mutex_init(&mutex,&attr); pthread_mutex_destroy(&attr); pthreadを呼び出すにはmutex_lock()の場合、mutexが他のスレッドにロックされている場合、この操作はずっとこの場所にブロックされます.ここでずっとブロックしたくない場合は、pthread_を呼び出すことができます.mutex_trylock. このとき反発量がロックされていない場合、pthread_mutex_trylockは0を返し、反発量にロックされます.反発量がロックされている場合は、すぐにEBUSYに戻ります.二、条件変数に必要なヘッダファイル:pthread.h条件変数識別子:pthread_cond_t 1、反発ロックに問題がある:反発ロックの明らかな欠点は、ロックと非ロックの2つの状態しかないことである.複数のスレッドが同じ共有リソースにアクセスする場合、いつ共有リソースを使用すべきか分からない簡単なシナリオを想定します.臨界領域に判断文を追加したり、有効にしたりすることができますが、効率が高くなく、複雑な環境では作成しにくい構造が必要です.条件が成立したときに対応するスレッドをトリガーすることができます.変数の変更とアクセスを行います.2、条件変数:条件変数は、スレッドがブロックされ、別のスレッドが信号を送信するのを待つことを許可する方法によって、反発ロックの不足を補い、反発ロックとともによく使用される.使用する場合、条件変数はスレッドをブロックするために使用され、条件が満たされない場合、スレッドは対応する反発ロックを解き、条件の変化を待つことが多い.他のスレッドが条件変数を変更すると、対応する条件変数に、この条件変数によってブロックされている1つ以上のスレッドが起動することを通知します.これらのスレッドは、反発ロックを再ロックし、条件が満たされているかどうかを再テストします.3、条件変数の相関関数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); 詳細説明:(1)条件変数の作成とログアウトは、反発ロックと同様に、静的動的の2つの作成方式a.静的静的方式PTHREAD_を使用するCOND_INITIALIZER定数、以下の通り:pthread_cond_t cond=PTHREAD_COND_INITIALIZER b.動的方式動的方式呼び出しpthread_cond_Init()関数、API定義:int pthread_cond_Init(pthread_cond_t*cond,pthread_condattr_t*cond_attr)POSIX規格では条件変数に属性が定義されているものの、LinuxThreadsでは実現していないためcond_attr値は通常NULLであり、無視される.条件変数をログアウトするにはpthread_を呼び出す必要があります.cond_destroy()は、スレッドがこの条件変数で待機していない場合にのみ、この条件変数をログアウトできます.そうしないと、EBUSYに戻ります.Linuxが実装する条件変数にはリソースが割り当てられていないため、ログアウト動作には待機スレッドがあるかどうかを確認するだけが含まれます.API定義は、int pthread_cond_destroy(pthread_cond_t*cond)(2)待機と励起a.待機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)/待ち待ち条件には、無条件待ちpthread_cond_wait()とタイミング待ちpthread_cond_timedwait()は、タイマ待ち方式が所定の時刻までに条件が満たされなければETIMEOUTに戻り、待機を終了し、abstime()システム呼び出しと同じ意味の絶対時間形式で現れ、0はグリニッジ時間1970年1月1日0時0分0秒を示す.いずれの待機方式でも、pthread_が複数のスレッドで同時に要求されることを防止するために、1つの反発ロックと組み合わなければならない.cond_wait()(またはpthread_cond_timedwait()、以下同)の競合条件(Race Condition).mutex反発ロックは通常ロック(PTHREAD_MUTEX_TIMED_NP)または適応ロック(PTHREAD_MUTEX_ADAPTIVE_NP)でなければならず、pthread_cond_wait()を呼び出す前に本スレッドによってロック(pthread_mutex_lock()されなければならず、更新条件待ちキューの前にmutexはロック状態が維持され、スレッドが保留中に入る前にロックを解除します.条件が満たされてpthread_を離れるcond_wait()の前にmutexはpthread_に入るために再ロックされます.cond_wait()前のロック動作に対応します.b.励起条件には2つの形態があり、pthread_cond_Signal()は、この条件を待つスレッドをアクティブにし、複数の待機スレッドが存在する場合、エンキュー順にそのうちの1つをアクティブにします.pthread_cond_broadcast()は、すべての待機スレッドをアクティブにします.(3)その他の操作pthread_cond_wait()とpthread_cond_timedwait()はいずれもキャンセルポイントとして実装されるため、ここで待機しているスレッドは直ちに再実行され、mutexを再ロックした後pthread_を離れるcond_wait()を実行し、キャンセル動作を実行します.つまりpthread_cond_wait()はキャンセルされ、mutexはロック状態を維持するため、コールバック関数を終了してロックを解除することを定義する必要があります.
  :

#include "pthread.h"
#include 
#include 
#include 


pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*      */
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*       */

void *firstThread(void *);
void *secondThread(void *);


int i=1;
int main(void)
{
    pthread_t t_a;
    pthread_t t_b;

    pthread_create(&t_a,NULL,firstThread,(void *)NULL);/*    t_a*/
    pthread_create(&t_b,NULL,secondThread,(void *)NULL); /*    t_b*/
    pthread_join(t_b, NULL);/*    t_b  */
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

 system("pause");
    exit(0);
	
}


void *firstThread(void *arg)
{
	for(i = 1;i<=10;++i)
	{
		pthread_mutex_lock(&mutex);/*     */

		if(i%2 == 0)
		{
			pthread_cond_signal(&cond);/*    ,    ,  t_b  */
		}
		else
		{
			printf("first thread:%d 
",i); } pthread_mutex_unlock(&mutex);/* */ Sleep(1); } return NULL; } void *secondThread(void *arg) { while(i<=10) { pthread_mutex_lock(&mutex); if(i%2 != 0) { pthread_cond_wait(&cond,&mutex);/* */ } printf("second thread:%d
",i); pthread_mutex_unlock(&mutex); Sleep(1); } return NULL; }
      vs2010    。   linux     ,#include"pthread.h"  #include   :gcc -o main main.c -lpthread