我想挂起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。是否可以在不使用条件的情况下暂停和恢复它?
7条答案
按热度按时间ifsvaxew1#
您的代码不正确-
pthread_cond_wait()
要求在您调用它时已经锁定互斥体:但是,这仍然是错误的。一个线程可以在任何时候从
pthread_cond_wait()
中唤醒,* 不一定 * 只有当它被发送信号时。这意味着您需要将pthread_cond_wait()
与某个共享状态配对,该状态对线程真正等待的条件进行编码-在最简单的情况下,您可以只使用一个标志变量。pthread_cond_signal()
用于告诉线程它应该唤醒并重新检查共享状态。将此应用于您的实现:提供互斥体的原因是为了保护共享状态并避免竞争条件-
pthread_cond_wait()
函数实际上在等待时执行原子解锁和等待,这允许避免“错过唤醒”。例如,在这段代码中,互斥体防止suspended
在suspended = true;
和pthread_cond_wait()
行之间变为false。unhi4e5o2#
如果一个线程没有等待某种条件,你怎么能“信号”它继续。它不能停止执行任何东西,然后神奇地重新开始,所以它等待一个条件。
具体来说,在pthreads中,恢复线程的方法实际上是使用条件变量。没有可用的API以任何其他方式挂起/恢复线程。等待
pthread_cond_wait
是廉价的,它会阻塞直到条件被发出信号,而不是使用(多?您使用条件来通知线程唤醒,并且需要互斥体来保护在唤醒时对条件变量和线程中的代码的访问。1wnzp6jl3#
条件总是与互斥体相关联。通常,线程会休眠,因为它在等待状态的改变来指示它有工作要做;你需要互斥体来保护对那个状态的访问,并需要条件来发出改变的信号。
唤醒一个线程而不告诉它你为什么唤醒它是一件有点奇怪的事情,所以没有特殊的方法来做;实现这一点的唯一方法是使用普通机制,但是没有共享状态。
如果出于某种原因,您希望从另一个线程挂起和恢复该线程,而不考虑要它完成的工作,那么您可以使用
pthread_kill
向它发送SIGSTOP
和SIGCONT
信号;我从来没有尝试过这样做,所以我不知道它是否支持。inkz8wg94#
互斥锁用于确保独占访问,而条件变量用于根据事件同步线程。
我们需要互斥体来确保条件变量不会在无限等待中结束。需要记住的一点是,锁和解锁的互斥操作保证是原子的,但条件变量不需要是原子的。也就是说,当条件变量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()对来自Thread 1的信号执行阻塞等待。(注意,对pthread_cond_wait()的调用自动地、原子地解锁关联的互斥变量,以便它可以被Thread 2使用)
4)一有信号,就醒过来。互斥体是自动和原子锁定的。
5)显式解锁互斥体
Thread2
1)做工作
2)锁关联互斥体
3)更改Thread 1正在等待的全局变量的值。
4)检查全局Thread 1等待变量的值。如果满足所需条件,则向Thread 1发送信号。
5)解锁互斥锁。继续
2sbarzqh5#
看起来没有任何Linux替代Windows API SuspendThread函数。在线程过程中不注入任何代码就不可能暂停Linux线程。
bf1o4zei6#
2010年6月29日由“caf”回复的代码是正确的,可以很好地同步两个协作线程。但是,suspendMe例程中的pthread_mutex_unlock是多余的,因为pthread_cond_wait嵌入了unlock。(pthread_mutex_unlock实际上返回一个错误,在大多数情况下这是无害的,但明智的代码平衡了每个锁与解锁。)代码应该是:
ql3eal8s7#
更重要的是-你最终想做什么?- 我想答案不是“暂停线程”。可能是你的程序设计有问题。