【问题标题】:How can you implement a condition variable using semaphores?如何使用信号量实现条件变量?
【发布时间】:2011-07-18 21:26:08
【问题描述】:

不久前,我在思考如何相互实现各种同步原语。例如,在 pthread 中,您可以获得互斥锁和条件变量,并且可以从中构建信号量。

在 Windows API(或者至少是旧版本的 Windows API)中有互斥锁和信号量,但没有条件变量。我认为应该可以从互斥锁和信号量中构建条件变量,但对于我来说,我就是想不出办法。

有没有人知道这样做的好结构?

【问题讨论】:

    标签: algorithm mutex semaphore condition-variable


    【解决方案1】:

    我可能在这里遗漏了一些东西,但似乎有一种比论文中描述的方式更简单的方法来从信号量和锁中实现条件。

    class Condition {
        sem_t m_sem;
        int   m_waiters;
        int   m_signals;
        pthread_mutex_t *m_mutex;
    public:
    
        Condition(pthread_mutex_t *_mutex){
            sem_init(&this->m_sem,0,0);
            this->m_waiters = 0;
            this->m_signals = 0;
            this->m_mutex = _mutex;
        }
        ~Condition(){}
        void wait();
        void signal();
        void broadcast();
    };
    
    void Condition::wait() {
        this->m_waiters++;
        pthread_mutex_unlock(this->m_mutex);
        sem_wait(&this->m_sem);
        pthread_mutex_lock(this->m_mutex);
        this->m_waiters--;
        this->m_signals--;
    }
    
    void Condition::signal() {
        pthread_mutex_lock(this->m_mutex);
        if (this->m_waiters && (this->m_waiters > this->m_signals)) {
            sem_post(&this->m_sem);
            this->m_signals++;
        }
        pthread_mutex_unlock(this->m_mutex);
    }
    

    【讨论】:

    • 我认为这应该主要工作,但从理论上讲,你的最后一个服务员可能会被线程调用信号在 sem_wait 和 pthread_mutex_lock 之间抢占 - 这会弄乱你的信号量值。为所有可能的线程交错正确处理这些事情是很棘手的。
    • Condition::wait() 方法在this->m_waiter++; 有一个临界区,无法正常工作
    【解决方案2】:

    在给定信号量的情况下实现 X 的一种方法是向系统添加一个服务器进程,使用信号量与其通信,并让该进程完成实现 X 的所有艰苦工作。作为一项学术练习,这可能是作弊,但它确实完成了工作,并且对于客户端进程的不当行为或它们的突然死亡,它可能更加稳健。

    【讨论】:

    • 嗯,除非“信号量”在 Windows API 中意味着完全不同的东西,否则它们不是您与之通信的东西。
    • 一个进程可以设置信号量,另一个进程可以测试它是否已设置。两台机器可以通过测试和设置几根电线的电压来传递任意消息。两个进程可以通过测试和设置信号量的状态来传递任意消息。在实践中,您可能只会使用信号量来调节对共享内存的访问,但我认为这两种情况都是通信——即使在第二种情况下,您所通信的只是“好的——您现在可以读取共享内存”。
    【解决方案3】:

    这里有一个paper from Microsoft Research [pdf],它正是处理这个问题。

    【讨论】:

      猜你喜欢
      • 2010-10-30
      • 1970-01-01
      • 2011-03-31
      • 2013-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多