实际上,这段代码不是线程安全的。互斥锁实际上并没有保护任何东西,使得隐含的谓词容易受到竞争条件的影响。
看看这段代码——互斥体保护的是什么?什么保护暂停/恢复状态?
void suspendMe()
{
pthread_mutex_lock(&m_SuspendMutex);
pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
}
void resumeMe()
{
pthread_cond_signal(&m_ResumeCond);
pthread_mutex_unlock(&m_SuspendMutex);
}
这是对的:
void suspendMe()
{ // tell the thread to suspend
pthread_mutex_lock(&m_SuspendMutex);
m_SuspendFlag = 1;
pthread_mutex_unlock(&m_SuspendMutex);
}
void resumeMe()
{ // tell the thread to resume
pthread_mutex_lock(&m_SuspendMutex);
m_SuspendFlag = 0;
phtread_cond_broadcast(&m_ResumeCond);
pthread_mutex_unlock(&m_SuspendMutex);
}
void checkSuspend()
{ // if suspended, suspend until resumed
pthread_mutex_lock(&m_SuspendMutex);
while (m_SuspendFlag != 0) pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
pthread_mutex_unlock(&m_SuspendMutex);
}
线程应该checkSuspend
在可以挂起的安全点调用。其他线程可以调用suspendMe
和resumeMe
暂停/恢复线程。
请注意,现在互斥锁保护了m_SuspendFlag
变量,确保线程被告知挂起,被告知恢复,并检查它是否应该挂起或在保护下保持挂起,使代码线程安全。
在这里使用2个单独的互斥锁不是更好吗,或者这是挂起pthread的正确方法?
使用两个互斥锁会破坏整个条件变量点。它们工作的整个机制是,您可以检查是否有您应该等待的东西,然后自动等待它,而无需在等待时持有锁或必须释放锁然后等待。如果您在等待时持有锁,那么其他线程如何更改状态?如果你释放锁然后等待,如果你错过了状态变化会发生什么?
顺便说一句,暂停或恢复线程几乎没有意义。如果你觉得你需要从外部暂停一个线程,那只是表明你对线程进行了编码来做一些你实际上并不希望它做的事情。关于暂停或恢复线程的问题通常表明线程编程的心理模型不正确。一个线程可能需要等待某些事情,但它不应该从外部“暂停”,因为它应该已经通过自己的编码知道它什么时候不应该做一些特定的工作。