不使用条件暂停pthreads

sle*_*eep 7 c++ linux pthreads

我想暂停pthreads,但显然,没有像pthread_suspend这样的函数.我在某处读到了使用互斥锁和条件暂停pthreads并使用如下:

#include <pthread.h>

class PThread {
public:
pthread_t myPthread;
pthread_mutex_t m_SuspendMutex;
pthread_cond_t m_ResumeCond;

void start() {
pthread_create(&myPthread, NULL, threadRun, (void*)this );
}

Thread() { }

void suspendMe() {
pthread_cond_wait(&m_ResumeCond,&m_SuspendMutex);
}

void resume() {
pthread_cond_signal(&m_ResumeCond);
}
};
Run Code Online (Sandbox Code Playgroud)

但我不明白为什么我们需要互斥和条件来暂停和恢复pthread.是否可以在不使用条件的情况下暂停和恢复它?

caf*_*caf 8

您的代码不正确 - pthread_cond_wait()要求在您调用互斥锁时已锁定互斥锁:

void suspendMe()
{
    pthread_mutex_lock(&m_SuspendMutex);
    pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
    pthread_mutex_unlock(&m_SuspendMutex);
}
Run Code Online (Sandbox Code Playgroud)

但是,这仍然是错误的.一个线程可以从醒来pthread_cond_wait()的任何名称,并不一定只有当它发出信号.这意味着您需要pthread_cond_wait()与某个共享状态配对,该状态编码线程正在等待的条件 - 在最简单的情况下,您可以只使用标志变量. pthread_cond_signal()用于告诉线程它应该唤醒并重新检查共享状态.将此应用于您的实现:

class PThread {
    public:

    pthread_t myPthread;
    bool suspended;
    pthread_mutex_t m_SuspendMutex;
    pthread_cond_t m_ResumeCond;

    void start() {
        suspended = false;
        pthread_create(&myPthread, NULL, threadRun, (void*)this );
    }

    Thread() { }

    void suspendMe() {
        pthread_mutex_lock(&m_SuspendMutex);
        suspended = true;
        do {
            pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
        } while (suspended);
        pthread_mutex_unlock(&m_SuspendMutex);
    }

    void resume() {
        /* The shared state 'suspended' must be updated with the mutex held. */
        pthread_mutex_lock(&m_SuspendMutex);
        suspended = false;
        pthread_cond_signal(&m_ResumeCond);
        pthread_mutex_unlock(&m_SuspendMutex);
    }
};
Run Code Online (Sandbox Code Playgroud)

提供互斥锁的原因是为了保护共享状态并避免竞争条件 - 该pthread_cond_wait()功能在等待时实际执行原子解锁和等待,这样可以避免"错过唤醒".例如,在此代码中,互斥锁防止suspendedsuspended = true;pthread_cond_wait()行之间更改为false .

  • 此外,您需要在唤醒后检查您的状况,因为系统*可能*以假错误的方式唤醒您的线程!例如,系统可能已经唤醒了10个线程,其中一个线程已经完成了这项工作. (3认同)
  • @Zan Lynx:是的,POSIX在这一点上非常明确:*"可能会发生来自pthread_cond_timedwait()或pthread_cond_wait()函数的虚假唤醒."*(尽管我认为Linux实现不会进行虚假的唤醒). (2认同)

Mar*_*k B 5

如果一个线程没有在某种条件下等待,你怎么能"发信号"它恢复.它不能只是停止执行任何事情,然后再次神奇地重新开始,所以等待条件.

详细说明,在pthreads中,恢复线程的方法实际上是使用条件变量.没有可用于以任何其他方式挂起/恢复线程的API.等待pthread_cond_wait是便宜的,它会阻止,直到条件发出信号,而不是使用(多?)CPU.您使用条件来通知线程唤醒,并且需要互斥锁来保护对条件变量的访问以及唤醒时线程中的代码.