繁体   English   中英

不使用条件暂停pthreads

[英]Suspend pthreads without using condition

我想暂停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。 是否可以在不使用条件的情况下暂停和恢复它?

您的代码不正确 - 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更改为false的之间suspended = true; pthread_cond_wait()行。

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

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

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

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

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

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

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

我们需要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)解锁互斥锁。 继续

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM