web-dev-qa-db-ja.com

pthreadミューテックスがロックまたはロック解除されているかどうかを確認します(スレッドがそれ自体をロックした後)。

Mutexがifステートメントでロックまたはロック解除されているかどうかを確認する必要があるので、次のように確認します...

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

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

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

では、ミューテックスがロックされているかどうかを確認するにはどうすればよいですか?

編集:

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

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

UPDATE:

Cafの提案に従ってプログラムを作り直しましたが、まだ問題が発生しています。私はできる限り最高の構造のカフェにプログラムを成形しましたが、今はデッドロックの原因を特定することさえできません...新しい質問を作成しました here コードの助けを求めています。

以下は、cafの提案の実行可能なバージョンです。スレッド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);
    }
}
_
16
ubiquibacon

ミューテックスは、実装するスキームに適したプリミティブではありません。 条件変数を使用する必要があります:

_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);
}
_

各スレッドは、他のスレッドがウェイクアップするように通知するまでpthread_cond_wait()でブロックします。これはデッドロックしません。

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

20
caf

pthread_mutex_trylockを使用できます。それが成功した場合、ミューテックスは要求されておらず、あなたは今それを所有しています(したがって、あなたはそれを解放し、あなたのケースでは「unhold」を返す必要があります)。そうでなければ、誰かがそれを持っています。

「mutexが要求されていないかどうかを確認する」ことは非常に悪い考えであることを強調しなければなりません。この種の考え方には固有の競合状態があります。そのような関数が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...
}
20
asveikau

Pthread_mutex_tとintを比較することはできません。

使用できます

int pthread_mutex_trylock(pthread_mutex_t *mutex);

それを確認します。

1
Huang F. Lei