【问题标题】:pthread-based event waking up only waiting threads基于 pthread 的事件只唤醒等待线程
【发布时间】:2010-10-29 12:34:54
【问题描述】:

在我的 C++ 程序中,我有一个 CEvent 类,它带有基于 pthreads 的触发器和等待成员函数(在 Linux 上运行)。如果有一个等待过程,实现是非常明显的(即网上有很多例子)。但是现在我需要满足多个线程正在等待事件的要求,并且在调用 trigger() 时应该全部可靠地唤醒。作为第二个条件,只有在调用 trigger() 时正在等待的线程才会被唤醒。

我当前的代码:

void CEvent::trigger() {
    pthread_mutex_lock(&mutex);
    wakeUp = true;
    pthread_cond_broadcast(&condition)
    pthread_mutex_unlock(&mutex);
    wakeUp = false;
}

void CEvent::wait() {
    pthread_mutex_lock(&mutex);
    while (!wakeUp)
        pthread_cond_wait(&condition, &mutex)

    pthread_mutex_unlock(&mutex);
}

这似乎几乎可以工作,因为在我将 wakeUp 设置回 false 之前等待唤醒的所有线程。但是在广播和wakeUp 的重置之间,调用wait() 的其他(或相同)线程也将立即唤醒,这是不可接受的。在 mutext 解锁之前设置 wakeUp = false 可以防止线程唤醒。

我的问题: * pthread_cond_broadcast 什么时候返回? IE。有没有保证它只会在所有线程都唤醒后才返回,或者它可以在之前返回? * 这个问题有什么推荐的解决方案吗?

【问题讨论】:

    标签: events pthreads


    【解决方案1】:

    请忽略我之前的虚假回答。在触发线程解锁互斥锁(从而释放等待的线程)和设置唤醒值之间存在竞争。这意味着另一个(不等待的)线程可以进来,获取互斥锁,并在wakeUp 中看到一个真实值,然后退出而无需等待。另一个错误是,在wakeUp 重置后,正在等待的线程会唤醒并立即恢复等待。

    解决此问题的一种方法是使用计数 - 每个正在等待的线程都会增加计数,然后触发器将等待,直到许多线程在恢复之前唤醒。然后,您必须确保在发生这种情况之前不允许非等待线程开始等待。

    // wake up "waiters" count of waiting threads
    void CEvent::trigger()
    {
        pthread_mutex_lock(&mutex);
    
        // wakey wakey
        wakeUp = true;
        pthread_cond_broadcast(&condition);
    
        // wait for them to awake
        while (waiters>0)
          pthread_cond_wait(&condition, &mutex);
    
        // stop waking threads up
        wakeUp = false;
    
        // let any "other" threads which were ready to start waiting, do so
        pthread_cond_broadcast(&condition);
        pthread_mutex_unlock(&mutex);
    }
    
    // wait for the condition to be notified for us
    void CEvent::wait()
    {
        pthread_mutex_lock(&mutex);
    
        // wait for us to be allowed to start waiting
        // we have to wait until any currrently being woken threads have gone
        while (wakeUp)
            pthread_cond_wait(&condition, &mutex);
    
        // our turn to start waiting
        waiters ++;
    
        // waiting
        while (!wakeUp)
            pthread_cond_wait(&condition, &mutex);
    
        // finished waiting, we were triggered
        waiters --;
    
        // let the trigger thread know we're done
        pthread_cond_broadcast(&condition);
        pthread_mutex_unlock(&mutex);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-18
      • 1970-01-01
      • 2021-08-09
      • 2020-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-05
      相关资源
      最近更新 更多