1

問題の論理的な解決策が思いつきません。メインと子の 2 つのストリームがあります。次に、次のようなメッセージを表示する必要があります。

...など、それぞれ10回。

pthread ミューテックスのみを使用でき、アイドル サイクルは使用できません。アイドル サイクルは、初期化段階でのみ許可されます。誰が - 誰かが良い解決策を知っていますか?

4

3 に答える 3

3

私はそれを理解したと思います...大きなヒントは、「初期化フェーズではアイドルのみを実行できる」ことです。

まず第一に、ミューテックスの制限は、ロックインしたのと同じスレッドでロックを解除する必要があるということです。したがってunlock()、スレッド内のそれぞれは とペアにするlock()必要があり、それらの数が同じでなければなりません (そうしないと、デッドロックが発生します)。 )。

つまり、スレッドが複数回印刷するのを防ぐ唯一の方法は、各スレッドが常に少なくとも 1 つの MUTEX を所有するようにすることです。スレッド B がいつでもすべてのミューテックスを解放し、その後 CPU がスレッド A に切り替わった場合、それは無期限に実行される可能性があります。

2 つのミューテックスではデッドロックなしでこれを行うことはできませんが、3 つでは可能です。

親スレッド:

    bool initDone = false;
    lock(m1);
    lock(m2);
    spawnChild();
    while (!initDone)
        sleep();
    while (true) {
        print("Parent");
        unlock(m1);
        lock(m3);
        unlock(m2);
        lock(m1);
        unlock(m3);
        lock(m2);
    }

子スレッド:

    lock(m3);
    initDone = true;
    while (true) {
        lock(m1);
        unlock(m3);
        lock(m2);
        print("Child");
        unlock(m1);
        lock(m3);
        unlock(m2);
    }

親がロック 1 と 2 を所有し、子がロック 3 を所有することから始めます。次に、ロックの解放と取得を交互に行います。親はロック 1 を子に、子はロック 3 を親に、親はロック 2 を子に、子はロック 1 を子供に渡します。親、親は子にロック 3 を与え、子は親にロック 2 を与え、繰り返します。

興味深い問題です。条件変数はこれを矮小化するため、条件変数の魅力がわかるはずです。

于 2013-10-28T18:50:52.477 に答える
0

必要なのは、相互に実行できる 2 つのスレッド (親と子) です。

これは疑似コードです。必要なロック プリミティブを自由に使用できます。

//global variables and initializations
parent_lock = UNLOCKED; //This allows your first print to be from parent
child_lock = LOCKED;

parent_counter = 0; //to count the number of prints 
child_counter = 0;

//Parent should do this                  |        //Child should do this
while(1)                                 |while(1)
{                                        |
spin: if(parent_lock == LOCKED)          |spin: if(child_lock == LOCKED)
      {                                  |      {
         //spin till child unlocks you   |      //spin till parent unlocks you
          goto spin;                     |          goto spin;
      }                                  |      }
      else                               |      else
      {                                  |      {
          print("PARENT");               |          print("CHILD");
          parent_counter++;              |          child_counter++;
          //lock yourself allow the other|          //lock yourself allow the other
          parent_lock = LOCKED;          |          child_lock = LOCKED;
          child_lock = UNLOCKED;         |          parent_lock = UNLOCKED;
          if (parent_counter == 10)      |          if (child_counter == 10)
          {                              |          {
              break;//printed 10 times   |              break;     
          }                              |          }
       }                                 |       }
}                                        |}

//PARENT has printed 10times wait for    |//CHILD has printed 10times wait for 
//child                                  |// parent

PS : *私が行ったロックで自由にスピンできると仮定します。そうでない場合は、スピンの代わりにスリープとウェイクアップを行うように上記のアルゴリズムを変更する必要があります。
*pthread ロック プリミティブを選択して、parent_lock と child_lock を初期化できます。
*プログラムが正しくなるためには、割り当てステートメントがアトミックであると仮定する必要があります。例: child_lock = LOCKED ステートメントはアトミックです。

非常に重要: 親の順序を参照してください:

parent_lock = LOCKED;
child_lock = UNLOCKED;

子スレッドの対応する部分。この 2 行を入れ替えると、(OS スケジューラによる) 親と子による一連の混合実行のため、DEADLOCK!!!! になる可能性があります。

于 2013-10-29T15:18:24.157 に答える