1

これが問題です。トイレは男性・女性どちらでもご利用いただけます。男性または女性が特定の時間にトイレにいる場合、反対の性別はトイレに入ることができず、待たなければなりません。すべての女性が出たら、男性が入ることができます.so、ここに私の解決策があります:

セマフォとミューテックスを使ってスレッド間で同期を取りたい。どのように実装するかについては、まだ明確ではありません。これが私が考えていることです:

  • スレッドをロック/ロック解除するためのミューテックスを作成します(トイレをロックします)。
  • トイレにいる人数をカウントするためのセマフォを作成します。性別ごとに1つ
  • セマフォ male_in_restroom;
  • セマフォ female_in_restroom;
  • 男性待ちの列、
  • 女性待ち行列、

最初に、どの性別がプロセスであるかを確認し、次に反対の性別のセフォアが 1 より大きいかどうかを確認します。そうでない場合は、トイレに入らせます。しかしトイレに異性がいる場合は、この処理を待たせてスリープ状態にする必要があります。

このプロセスを正確にスリープさせるにはどうすればよいですか?いくつかの例を探しましたが、まだ方法がわかりません。

wait()andの関数シグネチャを使用した例は、signal()非常に役立ちます。

4

2 に答える 2

0

これは十分に面白そうだったので、いくつかのコードを書きました。ただし、テストしていないため、何かが台無しになっている可能性がありますが、私が持っていたアイデアを実証するのに十分明確です.

typedef enum {
    none = -1,
    male = 0,
    female = 1
} sex_t;

class Human {
public:
    const sex_t id;
    Human(sex_t id_) : id(id_) {assert(id != none);}
};

class Restroom {
    tbb::spin_mutex     door_mutex;
    tbb::atomic<size_t> num_waiting;
    HANDLE              opposite_sex_can_enter;

    // these two variables need not be atomic, they're not accessed concurrently
    sex_t               current_occupying_sex;
    size_t              num_visitors;

public:
    Restroom() : current_occupying_sex(none), num_visitors(0) {
        num_waiting = 0;
        opposite_sex_can_enter = CreateEvent(0, TRUE, FALSE, 0);
    }

    void enter(const Human& h) {
        tbb::spin_mutex::scoped_lock lock(door_mutex);
        // this prevents any two humans trying to open the door (in any direction) at the same time :)
        if(current_occupying_sex == none) {
            // you're the first one in, so update the 'restroom id' and enter
            assert(num_visitors == 0 && num_waiting == 0);
            // if the knowledge of SetEvent has not propagated all the way yet and the same sex
            // person happens to walk into the restroom again, opposite sex people need to know
            // that they were slow and will need to wait again
            ResetEvent(opposite_sex_can_enter);
            current_occupying_sex = h.id;
            ++num_visitors;
        } else if(h.id == current_occupying_sex) {
            // you're not the first one in, but you're of the same sex, so you can just walk in
            assert(num_visitors > 0);
            ++num_visitors;
        } else {
            // you're not the first one in and you're of opposite sex, so you'll need to wait
            // first, let go of the door, you're not getting in :)
            lock.release();
            // then join the rest of the opposite sex people waiting
            ++num_waiting;
            WaitForSingleObject(opposite_sex_can_enter);
            --num_waiting;
            if(num_waiting == 0) {
                ResetEvent(opposite_sex_can_enter);
            }
            enter(h);
        }
    }

    void exit() {
        tbb::spin_mutex::scoped_lock lock(door_mutex);
        if(--num_visitors == 0) {
            current_occupying_sex = none;
            SetEvent(opposite_sex_can_enter);
            // fairness can be imposed here, meaning that if you're the last say, male
            // to walk out, you can check if females are waiting and switch the 
            // restroom sex id to female. The logic of enter() will change a little bit, but not radically.
        }
    }
};
于 2012-05-11T08:39:51.350 に答える
0

"トイレにいる人の数をカウントするためのセマフォを作成します。性別ごとに 1 つのセマフォ male_in_restroom; セマフォ female_in_restroom; 男性待ちのキュー、女性待ちのキュー、"

本当に意味がありません。セマフォ値の目的は、リソースが使用可能かどうかを示すことです。 値がゼロの場合、リソースは使用できません。 ゼロより大きい場合は使用可能です。では、リソースを使用して sem カウントを増やすことができた場合、セマフォにはどのような目的があるのでしょうか?

最初に、どの性別がプロセスであるかを確認し、次に反対の性別のセフォアが 1 より大きいかどうかを確認します。そうでない場合は、トイレに入らせます。

ダメダメダメ!あなたはそれを低音の良い場所に持っています。つまり、セマフォは任意の値を格納するためのものではありません。

さまざまなカウントなどはセマフォではなく通常の変数ですが、それらへのアクセスを制御するには、ミューテックス/セマフォ/条件変数 (ほとんどの場合: ミューテックス + 条件変数) を使用する必要があります。

また、何人の人が待っているかを追跡することが有用または重要であるとあなたが考える理由がわかりません。

于 2012-05-06T21:48:02.643 に答える