不使用条件暂停pthreads

时间:2010-06-29 13:05:52

标签: 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);
}
};

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

6 个答案:

答案 0 :(得分:8)

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

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

然而,这仍然是错误的。线程可以以任何名称从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);
    }
};

提供互斥锁的原因是为了保护共享状态并避免竞争条件 - pthread_cond_wait()函数在等待时实际执行原子解锁和等待,这允许“错过唤醒”避免。例如,在此代码中,互斥锁会阻止suspendedsuspended = true;行之间的pthread_cond_wait()更改为false。

答案 1 :(得分:5)

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

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

答案 2 :(得分:2)

条件始终与互斥锁相关联。通常,线程会休眠,因为它正在等待状态的改变以指示它有工作要做;你需要互斥锁来保护对该状态的访问,以及发出变化信号的条件。

唤醒一个线程而不告诉它为什么你会吵醒它是一件奇怪的事情,所以没有特别的方法去做;唯一的方法是使用普通机制,但没有共享状态。

如果由于某种原因你想要从另一个线程暂停和恢复该线程,而不是让它工作,那么你可以使用pthread_kill发送它SIGSTOP和{{ 1}}信号;我从来没有尝试过这样的事情,所以我不知道它是否得到支持。

答案 3 :(得分:0)

互斥锁用于确保独占访问,其中条件变量用于根据事件同步线程。

我们需要Mutexes来确保条件变量不会在无限等待中结束。 要记住的一件事是锁定和解锁的Mutex操作保证是原子的,但条件变量不一定是。即,当条件变量wait等待一半时,线程可以被调度。

考虑以下情况,不使用Mutex作为条件变量。

线程1


1)执行某些操作
2)等待条件变量
3)继续运作

线程2


1)执行一些操作
2)发出条件变量信号
3)继续操作

这里在线程1中,步骤2不保证是原子的。如果线程1在完成步骤1之前被调度程序推出RUNNING状态。 现在线程2开始执行并发出条件变量的信号。当线程1恢复执行时,它将完成剩余的低电平指令并开始等待。 线程1最终处于无限等待状态,因为条件变量的信号甚至在等待之前就已发生。

所以正确的使用方法是(我相信问题中提到的代码没有达到预期效果)

线程1: -


1)一直工作到必须发生某种情况的程度(例如“计数”必须达到指定值)
2)锁定相关的互斥锁
3)调用pthread_cond_wait()以对来自Thread1的信号执行阻塞等待。 (注意,对pthread_cond_wait()的调用会自动并原子地解锁相关的互斥锁变量,以便Thread2可以使用它
4)发出信号时,唤醒。互斥锁自动锁定原子。
5)明确解锁互斥锁

线程2


1)做好工作
2)锁定相关的互斥锁
3)更改Thread1正在等待的全局变量的值。
4)检查全局Thread1等待变量的值。如果它满足所需条件,则发出Thread1信号。
5)解锁互斥锁。 继续

答案 4 :(得分:0)

看起来没有任何Linux替代Windows API SuspendThread功能。如果没有在该线程过程中注入任何代码,就不可能暂停Linux线程。

答案 5 :(得分:-1)

更重要的是 - 你最终想做什么? - 我怀疑答案不是'暂停一个帖子'。可能是您的程序设计存在问题。