1. ホーム
  2. c

[解決済み] pthreadsの条件変数関数がmutexを必要とするのはなぜですか?

2022-04-20 17:59:40

質問

を読んでいるところです。 pthread.h 条件変数に関連する関数(例えば pthread_cond_wait(3) ) は、引数として mutex を必要とします。なぜ?私の知る限りでは、ミューテックスを作成するために ちょうど をその引数として使用するのですか?そのmutexは何をするものなのでしょうか?

どのように解決するのですか?

条件変数が実装されている(あるいは元々実装されていた)だけです。

ミューテックスは 条件変数そのもの . そのため、待ちを行う前にロックしておく必要があります。

待ち時間はミューテックスのロックを解除し、他の人が条件変数にアクセスできるようにします(シグナリングのため)。そして、条件変数がシグナルされるかブロードキャストされると、待機リストにある1つ以上のスレッドが起動され、そのスレッドのためにミューテックスが魔法のように再びロックされます。

条件変数がどのように機能するかを説明するために、一般的に次のような操作を目にすることがあります。次の例は、条件変数へのシグナルによって仕事を与えられるワーカスレッドです。

thread:
    initialise.
    lock mutex.
    while thread not told to stop working:
        wait on condvar using mutex.
        if work is available to be done:
            do the work.
    unlock mutex.
    clean up.
    exit thread.

このループの中では、waitが戻ったときに利用できるものがあれば、作業が行われる。このスレッドが作業を停止するフラグを立てると(通常は他のスレッドが終了条件を設定し、このスレッドを起動するために条件変数をキックします)、ループが終了し、ミューテックスが解除されて、このスレッドは終了します。

上のコードはシングルコンシューマーモデルで、作業が行われている間、ミューテックスはロックされたままです。マルチコンシューマモデルでは、以下のようにします。 :

thread:
    initialise.
    lock mutex.
    while thread not told to stop working:
        wait on condvar using mutex.
        if work is available to be done:
            copy work to thread local storage.
            unlock mutex.
            do the work.
            lock mutex.
    unlock mutex.
    clean up.
    exit thread.

で、このコンシューマが作業している間、他のコンシューマが作業を受けることができるようにします。

コンディション変数を使うことで、ある条件をポーリングする負担から解放され、代わりに何かが起こったときに他のスレッドから通知されるようになります。別のスレッドは、次のようにそのスレッドに仕事が可能であることを伝えることができます。

lock mutex.
flag work as available.
signal condition variable.
unlock mutex.

よく間違ってスプリアスウェイクアップと呼ばれるものの大半は、一般に、複数のスレッドがその pthread_cond_wait を呼び出すと(ブロードキャスト)、1つはミューテックスを持って戻り、作業を行い、そして再び待機します。

そうすると、2つ目のシグナライズされたスレッドは、何もすることがないときに出てくることができます。そのため、作業が行われることを示す追加の変数を用意する必要がありました(ここではcondvarとmutexのペアで本質的にmutex保護されていました - ただし、他のスレッドはそれを変更する前にmutexをロックする必要がありました)。

それは でした。 技術的には、スレッドが他のプロセスからキックされることなく条件待ちから戻ることは可能ですが(これは正真正銘の偽装ウェイクアップです)、私の長年の pthreads に関する作業、コードの開発/サービス、およびユーザーとしての作業のすべてにおいて、私は一度もこれを受けたことはありません。多分それは、HPがまともな実装をしていたからでしょう :-)

いずれにせよ、誤ったケースを処理する同じコードは、作業可能フラグが設定されないので、本物の偽のウェイクアップも処理します。