2011-08-03 11 views
0

私のプログラムはデッドロックの問題があるようです。 pthread_cond_wait()のmutexを解放しない原因として考えられるものはありますか?

は基本的に私はこのようになりますクラスがあります。 Fooのコンストラクタで

class Foo { 
public: 
    Foo(); 

    void bar(); 

private: 
    void monitor(); 

    bool condition_; 
    pthread_t monitor_; 
    pthread_mutex_t mutex_; 
    pthread_cond_t cv_; 
}; 

を、私は別のスレッド(すなわちmonitor_)でmonitor()を呼び出します。このmonitor()機能は以下のん:

pthread_mutex_lock(&mutex_); 
while (true) { 
    while (!condition_) { 
    pthread_cond_wait(&cv_, &mutex_); 
    } 
    // do something 
    // and then setting condition_ to false 
    condition_ = false; 
} 
pthread_mutex_unlock(&mutex_); 

bar()機能がFooの(ctorのとデストラクタを除く)のみ公開インタフェースです。また、実行時にミューテックスを取得する必要があります。私の症状はbar()は決してmutex_を得ることができないということです。 pthread_cond_wait()は、想定されているとおりにミューテックスを解放していないようです。そして、モニタスレッドを無効にすると(つまり競合状態がない場合)、bar()は問題なく完了することができます。

もちろん、上記のコードは私の実際のコードを削除したものです。実際に私はこのコードに論理エラーはないと思うし、pthreadを正しく使っています。このデッドロック状況の原因が他にあるのではないかと疑いがあります。誰かがこれに手がかりを与えることができますか?ありがとう!

+0

ところで、 'mutex_'と' cv_'は、どちらも属性がコンストラクタでNULLであるように適切に初期化されています。 –

+0

pthreadの使用には明らかに間違ったことはありません。あなたは私たちにコンストラクタを見せることができますか? –

答えて

0

私はあなたのコンストラクタとbar()関数を見て、誤って問題のオブジェクトのコピーを作ったとします。あなたが提供したクラスをコピーしました。残りのクラスの動作については、私が前提にしています。以下のプログラムは1秒ごとに起動し、スレッドに信号を送ります。あなたが再びこのに実行する場合

#include <pthread.h> 
#include <iostream> 

class Foo { 
public: 
    Foo() { 
    condition_ = false; 
    pthread_mutex_init(&mutex_, NULL); 
    pthread_cond_init(&cv_, NULL); 
    pthread_create(&monitor_, NULL, 
      startFunc, this); 
    } 

    void bar() { 
    pthread_mutex_lock(&mutex_); 
    std::cout << "BAR" << std::endl; 
    condition_ = true; 
    pthread_cond_signal(&cv_); 
    pthread_mutex_unlock(&mutex_); 
    } 

private: 
    Foo(const Foo&) {}; 
    Foo& operator=(const Foo&) { return *this; }; 

    static void* startFunc(void* r) { 
    Foo* f = static_cast<Foo*>(r); 
    f->monitor(); 
    return NULL; 
    } 

    void monitor() { 
    pthread_mutex_lock(&mutex_); 
    while (true) { 
     while (!condition_) { 
    pthread_cond_wait(&cv_, &mutex_); 
     } 
     // do something 
     // and then setting condition_ to false 
     std::cout << "FOO" << std::endl; 
     condition_ = false; 
    } 
    pthread_mutex_unlock(&mutex_); 

    } 

    bool condition_; 
    pthread_t monitor_; 
    pthread_mutex_t mutex_; 
    pthread_cond_t cv_; 
}; 


int main() { 
    struct timespec tm = {1,0}; 
    Foo f; 

    while(true) { 
    f.bar(); 
    nanosleep(&tm, NULL); 
    } 

} 
+0

これはとても奇妙です。私はちょうど再起動し、 "クリーン"を行い、その後再作成しました。意外にも、それは働いた。私はまだ理由を理解できません。 OSがリソース不足の可能性があります。とにかく、あなたが "誤ってオブジェクトをコピーする"ということは、私に多くの警告をします。私はこれを受け入れたものとして選ぶでしょう。ありがとう。 –

0

私の賭けは、それがここで失敗したということです。

while (!condition_) { 
    pthread_cond_wait(&cv_, &mutex_); 
} 

条件がfalseである、のと仮定しましょう。あなたはwhileループに入り、最初の実行ではすべてがうまくいく、つまり、mutexのロックを解除し、決定変数を待つ。条件変数は変更されますが、ブール値は変更されません。条件?その場合は、初期化されていないmutexでpthread_cond_waitと入力し、未定義の動作が発生する可能性があります... bar()メソッドも表示すると助けになると思います。

もう1つの推測はスレッドの優先順位です。スレッドをより良い機会に切り替えるために、利回りを挿入することがあります。

+0

いいえ、そうではありません。 cvが通知された場合、pthread_cond_waitが返される前にmutexが再取得されます。ループすると(条件はまだ偽です)、ロックを解除してもう一度待機します。実際には、ifを使用して誤った起動を処理できない誤った実装が多数見られましたが、これは起こることが許されています。 –

+0

ありがとう、@KPK。 @ dave-sも示唆しているように、あなたは偽の起床に言及していたと思います。私はここでwhileループを使用しているので、その可能性は低いです。私のトレースは、 'pthread_mutex_lock()'から始まる 'bar()'のコードが決して実行される機会を得なかったことを示しているので、 'bar()'を表示することは役に立たないでしょう。あなたはまた私にスレッドを提出することを提案していました。収入は誰ですか? –

0

、私は他のスレッドがミューテックスをロックすることができるようにcond_waitは、ミューテックスを解放するために期待していたデッドロック、へ走っていた非常に似たような状況に遭遇しました。

私の問題は、mutexを(settype-> PTHREAD_MUTEX_RECURSIVE_NPで)再帰的に設定していて、誤ってmutexをcond_wait呼び出しの前に2回ロックしていたことでした。 cond_waitは一度ロックを解除しただけなので、mutexはまだロックされていました。明白な修正は、それを一度だけロックすることでした。また、教訓として、本当に必要な場合を除き、再帰的なミューテックス設定は使用しません。

関連する問題