C++ 在不使用条件的情况下挂起pthreads

C++ 在不使用条件的情况下挂起pthreads,c++,linux,pthreads,C++,Linux,Pthreads,我想挂起pthread,但显然没有pthread_suspend这样的函数。我在某处读到关于使用互斥体和条件挂起pthread的内容,并按如下方式使用它: #include <pthread.h> class PThread { public: pthread_t myPthread; pthread_mutex_t m_SuspendMutex; pthread_cond_t m_ResumeCond; void start() { pthread_create(&my

我想挂起pthread,但显然没有pthread_suspend这样的函数。我在某处读到关于使用互斥体和条件挂起pthread的内容,并按如下方式使用它:

#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{
公众:
pthread_t myPthread;
pthread_mutex_t m_SuspendMutex;
pthread_cond_t m_ResumeCond;
void start(){
pthread_创建(&myPthread,NULL,threadRun,(void*)this);
}
线程(){}
void suspendMe(){
pthread_cond_wait(&m_ResumeCond,&m_SuspendMutex);
}
作废简历(){
pthread_cond_信号(&m_ResumeCond);
}
};

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

如果某个线程没有等待某个条件或其他条件,您如何“发出信号”让它恢复。它不能停止执行任何东西,然后神奇地重新开始,所以它需要等待一个条件


更详细地说,在pthreads中,恢复线程的方法实际上是使用条件变量。没有API可用于以任何其他方式挂起/恢复线程。等待
pthread\u cond\u wait
的成本很低,它会阻塞直到发出信号,而不使用(很多?)CPU。您使用条件向线程发出唤醒信号,并且需要互斥锁来保护对条件变量和唤醒时线程中代码的访问。

您的代码不正确-调用时,
pthread\u cond\u wait()
要求已锁定互斥锁:

void suspendMe()
{
    pthread_mutex_lock(&m_SuspendMutex);
    pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
    pthread_mutex_unlock(&m_SuspendMutex);
}
然而,这仍然是错误的。线程可以以任何名称从
pthread\u cond\u wait()
唤醒,而不一定只有在发出信号时才唤醒。这意味着您需要将
pthread\u cond\u wait()
与一些共享状态配对,这些共享状态对线程真正等待的条件进行编码——在最简单的情况下,您可以只使用一个标志变量
pthread\u cond\u 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\u cond\u wait()
函数实际上在等待时执行原子解锁和等待,从而避免“错过唤醒”。例如,在此代码中,互斥锁防止
suspended
suspended=true之间变为false
pthread\u cond\u wait()
行。

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

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


如果出于某种原因,您想从另一个线程挂起并恢复该线程,而不让它执行工作,那么您可能可以使用
pthread_kill
发送
SIGSTOP
SIGCONT
信号;我从未尝试过这样做,所以我不知道它是否受支持。

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

我们需要互斥来确保条件变量不会以无限等待结束。 需要记住的一点是,锁和解锁的互斥操作保证是原子的,但条件变量不必是原子的。i、 当条件变量wait在中途时,线程可以被调度出去

考虑以下情况,条件变量为out Mutex

线程1
1)执行一些操作
2) 等待条件变量
3) 继续操作

线程2
1)执行一些操作
2) 向条件变量发送信号
3) 继续操作

在线程1中,步骤2不能保证是原子的。如果调度程序在完成步骤1之前将线程1推出运行状态。 现在线程2开始执行并向条件变量发送信号。当线程1恢复执行时,它将完成剩余的低级指令并开始等待。 线程1以无限等待结束,因为条件变量的信号甚至在等待之前就出现了

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

线程1:-
1)一定要工作到某个特定条件必须出现的点(例如“计数”必须达到指定值)
2) 锁关联互斥
3) 调用pthread_cond_wait()来执行来自Thread1的阻塞等待信号。 (请注意,对pthread_cond_wait()的调用会自动且自动地解锁关联的互斥变量,以便Thread2可以使用它)
4) 当信号响起时,醒来。互斥锁是自动和原子锁定的。
5) 显式解锁互斥锁

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

更切题-你最终想做什么??-我怀疑答案不是“挂起线程”。可能是您的程序设计有问题。

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

此外,您需要在唤醒后检查您的条件,因为系统可能会在条件为false时唤醒您的线程!例如,系统可能已经唤醒了10个线程,其中一个线程已经完成了任务。@Zan Lynx:yes,POSIX在这一点上非常清楚:“从p