我想暂停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。是否可以在不使用条件的情况下暂停和恢复它?
答案 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()
函数在等待时实际执行原子解锁和等待,这允许“错过唤醒”避免。例如,在此代码中,互斥锁会阻止suspended
和suspended = 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)执行某些操作
2)等待条件变量
3)继续运作
1)执行一些操作
2)发出条件变量信号
3)继续操作
这里在线程1中,步骤2不保证是原子的。如果线程1在完成步骤1之前被调度程序推出RUNNING状态。 现在线程2开始执行并发出条件变量的信号。当线程1恢复执行时,它将完成剩余的低电平指令并开始等待。 线程1最终处于无限等待状态,因为条件变量的信号甚至在等待之前就已发生。
所以正确的使用方法是(我相信问题中提到的代码没有达到预期效果)
1)一直工作到必须发生某种情况的程度(例如“计数”必须达到指定值)
2)锁定相关的互斥锁
3)调用pthread_cond_wait()以对来自Thread1的信号执行阻塞等待。
(注意,对pthread_cond_wait()的调用会自动并原子地解锁相关的互斥锁变量,以便Thread2可以使用它
4)发出信号时,唤醒。互斥锁自动锁定原子。
5)明确解锁互斥锁
1)做好工作
2)锁定相关的互斥锁
3)更改Thread1正在等待的全局变量的值。
4)检查全局Thread1等待变量的值。如果它满足所需条件,则发出Thread1信号。
5)解锁互斥锁。
继续
答案 4 :(得分:0)
看起来没有任何Linux替代Windows API SuspendThread功能。如果没有在该线程过程中注入任何代码,就不可能暂停Linux线程。
答案 5 :(得分:-1)
更重要的是 - 你最终想做什么? - 我怀疑答案不是'暂停一个帖子'。可能是您的程序设计存在问题。