【问题标题】:Using sempaphore and calling wait() and signal()使用信号量并调用 wait() 和 signal()
【发布时间】:2012-05-06 21:22:30
【问题描述】:

这就是问题所在。厕所可以由男性或女性一次使用。如果男性或女性在给定时间在洗手间,则异性不能进入洗手间并必须等待。一旦所有的女性都出去了,那么男性就可以进入。所以,这是我的解决方案:

我想使用信号量和互斥量在线程之间执行同步。我仍然不清楚如何实现它。 这是我的想法:

  • 创建一个互斥锁来锁定/解锁线程。(锁定厕所)
  • 创建一个信号量来计算洗手间的人数。每个性别一个
  • 信号量 male_in_restroom;
  • 信号量 female_in_restroom;
  • 等待男性排队,
  • 等待女性排队,

首先,我检查进程是什么性别,然后检查相反性别的信号量是否大于 1。如果不是,我让他们进入洗手间。但是如果厕所里已经有异性了,我需要让这个过程等待并让它休眠。

我该如何让这个进程进入休眠状态?我找了一些例子,但仍然不知道该怎么做。

wait() 和 signal() 的函数签名示例将非常有帮助。

【问题讨论】:

  • 等待一个条件变量怎么样?
  • 这不是你的问题,但你不需要两个信号量。一个跟踪性别的变量和一个信号量就足够了。
  • 这与现实世界的运作方式非常不同。一个浴室里的男孩+女孩是一种明显的可能性,至少需要 10 分钟。以你自己的方式塑造世界的运作方式。

标签: c++ multithreading semaphore


【解决方案1】:

"创建一个信号量来计算洗手间的人数。一个 对于每个性别信号量male_in_restroom;信号量 female_in_restroom; 男排队,女排队,”

确实没有意义。信号量值的目的是指示资源是否可用。 如果值为零,则资源不可用。如果大于零,则资源可用。因此,如果您设法通过使用资源增加 sem 计数,那么信号量有什么用途?

所以首先,我检查了这个过程是什么性别,然后我检查了 异性的信号量大于一。如果不是我让他们 进入洗手间。

不不不!你有它的低音。这强调了一点:信号量不是用来存储任意值的。

您的各种计数等是正常变量,而不是信号量,但是,您必须使用互斥体/信号量/条件变量(最有可能:互斥体 + 条件变量)来控制对它们的访问.

另外,我不知道您为什么认为跟踪有多少人在等待是有用或重要的。

【讨论】:

    【解决方案2】:

    这看起来很有趣,所以我写了一些代码。虽然还没有测试过,所以可能搞砸了,但它足以证明我的想法。

    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.
            }
        }
    };
    

    【讨论】:

    • 对不起,调用WaitForSingleObject出错了,需要WaitForSingleObject(opposite_sex_can_enter, INFINITE);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-30
    • 2013-05-27
    • 2013-02-02
    • 2016-08-30
    相关资源
    最近更新 更多