2010-12-06 7 views
13

私はミューテックスがif文でロックまたはロック解除された場合に確認する必要があります...チェック

if(mutex[id] != 2){ 
    /* do stuff */ 
} 

が、私はそれをチェックしたときにgccが私に次のエラーを与える:

error: invalid operands to binary != (have 'ptherad_mutex_t' and 'int')

それでは、どのように私は、mutexがロックされているかされていないかどうかを確認することができますか?

EDIT:

私の問題への重要な要素は、(設計上)私のスレッドが右別のスレッドに制御を渡した後に自分自身をロックしていることです。したがって、スレッドAがスレッドBに制御を渡すと、スレッドAがロックされ、スレッドBが何らかの処理を行い、スレッドBが完了するとスレッドAのロックが解除されます。

スレッドBがスレッドAのロックを解除しようとするとスレッドAがまだロックを完了していない場合、ロック解除の呼び出しは失われ、スレッドAはロックされたままであり、デッドロックが発生します。

UPDATE:

私はカフェの提案を取ったが、私はまだ問題に実行しています私のプログラムをリメイク。私は自分のプログラムを構造カフにモールドして最高の状態で提供していますが、今はデッドロックを引き起こしていることを伝えることさえできません...私は新しい質問hereを作成しました。

以下は、カフェの提案の実行可能なバージョンです。私はスレッドaの関数で小さな並べ替えを行いました。スレッドaとスレッドbの両方が作成時にロックされず、決して変更できない状態を待っていました。

#include <pthread.h> 

int run_a = 0; 
pthread_mutex_t lock_a = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t cond_a = PTHREAD_COND_INITIALIZER; 

int run_b = 0; 
pthread_mutex_t lock_b = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t cond_b = PTHREAD_COND_INITIALIZER; 

void *a(void *); 
void *b(void *); 

int main(){ 
    int status; 
    pthread_t thread_a; 
    pthread_t thread_b; 

    pthread_create(&thread_a, NULL, a, (void *)0); 
    pthread_create(&thread_b, NULL, b, (void *)0); 

    pthread_join(thread_a, (void **)&status); 
    pthread_join(thread_b, (void **)&status); 

} 

/* thread A */ 
void *a(void *i){ 
    while (1) { 
     printf("thread A is running\n"); 
     sleep(1); 

     /* unlock thread B */ 
     pthread_mutex_lock(&lock_b); 
      run_b = 1; 
      pthread_cond_signal(&cond_b); 
     pthread_mutex_unlock(&lock_b); 

     /* wait for thread A to be runnable */ 
     pthread_mutex_lock(&lock_a); 
      while (!run_a) 
       pthread_cond_wait(&cond_a, &lock_a); 
      run_a = 0; 
     pthread_mutex_unlock(&lock_a);  
    } 
} 

/* thread B */ 
void *b(void *i){ 
    while (1) { 
     /* wait for thread B to be runnable */ 
     pthread_mutex_lock(&lock_b); 
      while (!run_b) 
       pthread_cond_wait(&cond_b, &lock_b); 
      run_b = 0; 
     pthread_mutex_unlock(&lock_b); 

     printf("thread B is running\n"); 
     sleep(1); 

     /* unlock thread A */ 
     pthread_mutex_lock(&lock_a); 
      run_a = 1; 
      pthread_cond_signal(&cond_a); 
     pthread_mutex_unlock(&lock_a); 
    } 
} 
+0

mutexesはロックされたスレッドによってロック解除されなければなりません。あるスレッドによってロックされ、別のスレッドによってロック解除されるロック構造が必要な場合は、セマフォを使用する必要があります(または上の例のように独自のセマフォを構築する必要があります)。あるスレッドがmutxをロックし、別のスレッドがロックを解除すると、本当に醜い同期バグが発生する可能性があります。 –

答えて

16

ミューテックスは、実装したいスキームの正しいプリミティブではありません。各スレッドは、それが目を覚ますために、他のスレッド信号までpthread_cond_wait()にブロックします

int run_thread_a = 0; 
pthread_mutex_t run_lock_a = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t run_cond_a = PTHREAD_COND_INITIALIZER; 

int run_thread_b = 0; 
pthread_mutex_t run_lock_b = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t run_cond_b = PTHREAD_COND_INITIALIZER; 

/* thread A */ 
while (1) { 
    /* Wait for Thread A to be runnable */ 
    pthread_mutex_lock(&run_lock_a); 
    while (!run_thread_a) 
     pthread_cond_wait(&run_cond_a, &run_lock_a); 
    run_thread_a = 0; 
    pthread_mutex_unlock(&run_lock_a); 

    /* Do some work */ 

    /* Now wake thread B */ 
    pthread_mutex_lock(&run_lock_b); 
    run_thread_b = 1; 
    pthread_cond_signal(&run_cond_b); 
    pthread_mutex_unlock(&run_lock_b); 
} 

/* thread B */ 
while (1) { 
    /* Wait for Thread B to be runnable */ 
    pthread_mutex_lock(&run_lock_b); 
    while (!run_thread_b) 
     pthread_cond_wait(&run_cond_b, &run_lock_b); 
    run_thread_b = 0; 
    pthread_mutex_unlock(&run_lock_b); 

    /* Do some work */ 

    /* Now wake thread A */ 
    pthread_mutex_lock(&run_lock_a); 
    run_thread_a = 1; 
    pthread_cond_signal(&run_cond_a); 
    pthread_mutex_unlock(&run_lock_a); 
} 

:あなたは条件変数を使用する必要があります。これはデッドロックしません。

スレッドごとにint,pthread_cond_tおよびpthread_mutex_tの1つを割り当てることで、簡単に多くのスレッドに拡張できます。

+0

@caf私はもともと条件を使用しようとしましたが、スレッドを同時に実行する必要があります。また、それぞれの条件を作成しない限り(条件の配列は機能しません。どのように私はこの仕事をすることができます表示されません。 – ubiquibacon

+0

@typoknig:条件の配列はまさに必要なものです。 「スレッドによってアクセスされるたびにブロックされません」。各条件変数は独立しています。配列に保存するか別名のグローバルにするかは関係ありません。 – caf

+0

@caf私は自分の質問を更新し、自分のコードを追加しました。おそらくあなたはそれを見てみるかもしれません。あなたが提案した構造が正しいことは知っていますが、私はまだそれを正しく動作させることができません(更新された質問を参照)。私が投稿したコードは、私が質問したときから完全に書き直されています(現在は条件を使用しています)。 – ubiquibacon

18

pthread_mutex_trylockを使用できます。それが成功すれば、ミューテックスは請求されず、あなたはそれを所有しています(あなたはそれを解放し、あなたのケースでは "unheld"を返すべきです)。さもなければ、誰かがそれを持っています。

「ミューテックスが請求されていないかどうかを確認する」ということは非常に悪いことですが、この種の思考には、固有の競争条件があります。そのような関数が、時刻がtのときにロックが解除されていると言えば、他のスレッドがt+1でロックを取得したかどうかはまったく分かりません。

は場合、これはコード例とのより良い例示されている、考えてみます。

bool held = is_lock_held(); 

if (!held) 
{ 
    // What exactly can you conclude here? Pretty much nothing. 
    // It was unheld at some point in the past but it might be held 
    // by the time you got to this point, or by the time you do your 
    // next instruction... 
} 
+0

私の問題は、スレッドを制御して別のスレッドに渡し(b)、ロックしてしまうことです。スレッド「b」が実行されると、スレッド「a」がロック解除されてロックされる。システムは素晴らしいですが、まれにスレッド 'b'がスレッド' a'をロックする前にスレッド 'a'を"ロック解除 "するので、"ロック解除 "が失われ、プログラムがデッドロックします。私は 'trylock'を使用しようとしましたが、あなたが提案した方法ではありません...私はもう一度やり直します。 – ubiquibacon

+0

@typoknig - シンプルな同期スキームを考慮する必要があります。たとえば、BがAが待っているセマフォをシグナルすることができます。 – asveikau

+0

@asveikau問題は、スレッドAには制御があり、それ自体をロックする必要があるということです。スレッドAはスレッドAをロックする速度を制御できません。 BはスレッドBの完了時にスレッドAのセマフォのシグナル/ロック解除を行いますが、スレッドAがまだロックしていない場合(スレッドBがロック解除の信号を出した後に)スレッドAはロックされたままです。 – ubiquibacon

0

あなたはint型でpthread_mutex_tを比較することはできません。

あなたはそれをチェックするために

int pthread_mutex_trylock(pthread_mutex_t *mutex);

を使用することができます。