简体   繁体   English

不使用条件暂停pthreads

[英]Suspend pthreads without using condition

I want to suspend pthreads but apparently, there is no such function as pthread_suspend. 我想暂停pthreads,但显然,没有像pthread_suspend这样的函数。 I read somewhere about suspending pthreads using mutexes and conditions and used it as following: 我在某处读到了使用互斥锁和条件暂停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);
}
};

but I don't understand why we need both mutex and condition to suspend and resume a pthread. 但我不明白为什么我们需要互斥和条件来暂停和恢复pthread。 Is it possible to suspend and resume it without using conditions? 是否可以在不使用条件的情况下暂停和恢复它?

Your code is not correct - the pthread_cond_wait() requires that the mutex be locked already when you call it: 您的代码不正确 - pthread_cond_wait()要求在您调用互斥锁时已锁定互斥锁:

void suspendMe()
{
    pthread_mutex_lock(&m_SuspendMutex);
    pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
    pthread_mutex_unlock(&m_SuspendMutex);
}

However, this is still wrong. 但是,这仍然是错误的。 A thread can wake up from pthread_cond_wait() at any name, not necessarily only when it is signalled. 一个线程可以从醒来pthread_cond_wait()任何名称, 并不一定只有当它发出信号。 This means that you need to pair pthread_cond_wait() with some shared state that encodes the condition that the thread is really waiting for - in the simplest case, you can just use a flag variable. 这意味着您需要将pthread_cond_wait()与某个共享状态配对,该共享状态对线程实际等待的条件进行编码 - 在最简单的情况下,您可以使用标志变量。 pthread_cond_signal() is used to tell the thread that it should wake and re-check the shared state. pthread_cond_signal()用于告诉线程它应该唤醒并重新检查共享状态。 Applying this to your implementation: 将此应用于您的实现:

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);
    }
};

The reason the mutex is provided is to protect the shared state and avoid race conditions - the pthread_cond_wait() function actually performs an atomic-unlock-and-wait when it waits, which allows a "missed wakeup" to be avoided. 提供互斥锁的原因是为了保护共享状态并避免竞争条件 - pthread_cond_wait()函数在等待时实际执行原子解锁和等待,这样可以避免“错过唤醒”。 For example in this code, the mutex prevents suspended from changing to false in between the suspended = true; 例如,在该代码时,互斥防止suspended更改为false的之间suspended = true; and pthread_cond_wait() lines. pthread_cond_wait()行。

If a thread wasn't waiting on some condition or other, how could you "signal" it to resume. 如果一个线程没有在某种条件下等待,你怎么能“发信号”它恢复。 It can't just stop executing anything at all and then magically start again, so it waits on a condition. 它不能只是停止执行任何事情,然后再次神奇地重新开始,所以等待条件。

To elaborate, in pthreads, the way to resume a thread is in fact to use condition variables. 详细说明,在pthreads中,恢复线程的方法实际上是使用条件变量。 There isn't an API available to suspend/resume a thread in any other way. 没有可用于以任何其他方式挂起/恢复线程的API。 Waiting on pthread_cond_wait is cheap, it blocks until the condition is signaled, not using (much?) CPU. 等待pthread_cond_wait是便宜的,它会阻塞直到条件发出信号,而不是使用(多?)CPU。 You use the condition to signal the thread to wake up, and the mutex is required to protect access to the condition variable and the code in the thread upon wakeup. 您使用条件来通知线程唤醒,并且需要互斥锁来保护对条件变量的访问以及唤醒时线程中的代码。

A condition is always associated with a mutex. 条件始终与互斥锁相关联。 Usually, a thread will sleep because it's waiting for a change of state to indicate that it has work to do; 通常,线程会休眠,因为它正在等待状态的改变以指示它有工作要做; you need the mutex to guard access to that state, and the condition to signal the change. 你需要互斥锁来保护对该状态的访问,以及发出变化信号的条件。

Waking up a thread without telling it why you've woken it is a bit of an odd thing to do, so there's no special way to do it; 唤醒一个线程而不告诉它为什么你会唤醒它是一件有点奇怪的事情,所以没有特别的方法去做; the only way to do it is to use the normal mechanism, but with no shared state. 唯一的方法是使用普通机制,但没有共享状态。

If for some reason you want to suspend and resume the thread from another thread, independently from giving it work to do, then you might be able to use pthread_kill to send it SIGSTOP and SIGCONT signals; 如果由于某种原因你想要从另一个线程暂停和恢复线程,而不是让它工作,那么你可以使用pthread_kill向它发送SIGSTOPSIGCONT信号; I've never tried doing anything like that, so I've no idea whether or not it's supported. 我从来没有尝试过这样的事情,所以我不知道它是否得到支持。

It looks like there are no any Linux alternatives to Windows API SuspendThread function. 看起来没有任何Linux替代Windows API SuspendThread功能。 It is impossible to pause Linux thread without injection any code in that thread procedure. 如果不在该线程过程中注入任何代码,则无法暂停Linux线程。

Mutexes are used to ensure the exclusive access , where as condition variables are used to synchronize threads based on the events. 互斥锁用于确保独占访问,其中条件变量用于根据事件同步线程。

We need Mutexes to ensure that condition variables dont end up in an infinite wait. 我们需要Mutexes来确保条件变量不会在无限等待中结束。 One thing to remember is Mutex operation of lock and unlock are guaranteed to be atomic, but the condition variables need not be. 要记住的一件事是锁定和解锁的Mutex操作保证是原子的,但条件变量不一定是。 ie The thread can get scheduled out while the condition variable wait is half way. 即,当条件变量wait等待一半时,线程可以被调度。

Consider the following case with out Mutex for condition variable. 考虑以下情况,使用Mutex作为条件变量。

Thread 1 线程1


1)Perform Some Operation 1)执行某些操作
2)Wait on the Condition Variable 2)等待条件变量
3)Continues the Operation 3)继续操作

Thread 2 线程2


1) Perform some operation 1)执行一些操作
2)Signal the Condition Variable 2)发出条件变量的信号
3)Continue the Operation 3)继续操作

Here in the Thread 1 , the step 2 is not guaranteed to be atomic. 在线程1中,步骤2不保证是原子的。 If the Thread 1 is pushed out of RUNNING state by scheduler before it completes the step1. 如果线程1在完成步骤1之前被调度程序推出RUNNING状态。 Now Thread 2 starts executing and signals the condition variable. 现在线程2开始执行并发出条件变量的信号。 When Thread 1 resumes execution it will finish the remaining low level instructions and starts waiting. 当线程1恢复执行时,它将完成剩余的低电平指令并开始等待。 Thread 1 ends up in an infinite wait, as the signal of condition variable occurred even before the wait. 线程1在无限等待中结束,因为条件变量的信号甚至在等待之前发生。

So the Right way to use is (I believe the code mentioned in the question doesnt do the expected) 所以正确的使用方法是(我相信问题中提到的代码没有达到预期效果)

Thread 1 :- 线程1: -


1)Do work up to the point where a certain condition must occur (such as "count" must reach a specified value) 1)工作到必须发生某种情况的程度(例如“计数”必须达到指定值)
2)Lock associated mutex 2)锁定相关的互斥锁
3)Call pthread_cond_wait() to perform a blocking wait for signal from Thread1. 3)调用pthread_cond_wait()以对来自Thread1的信号执行阻塞等待。 ( Note that a call to pthread_cond_wait() automatically and atomically unlocks the associated mutex variable so that it can be used by Thread2) (注意,对pthread_cond_wait()的调用会自动并原子地解锁相关的互斥锁变量,以便Thread2可以使用它
4)When signalled, wake up. 4)发出信号时,唤醒。 Mutex is automatically and atomically locked. 互斥锁自动锁定原子。
5)Explicitly unlock mutex 5)明确解锁互斥锁

Thread2 线程2


1)Do work 1)做好工作
2)Lock associated mutex 2)锁定相关的互斥锁
3)Change the value of the global variable that Thread1 is waiting upon. 3)更改Thread1正在等待的全局变量的值。
4)Check value of the global Thread1 wait variable. 4)检查全局Thread1等待变量的值。 If it fulfills the desired condition, signal Thread1. 如果它满足所需条件,则发出Thread1信号。
5)Unlock mutex. 5)解锁互斥锁。 Continue 继续

More to the point - what are you ultimately trying to do?? 更重要的是 - 你最终想做什么? - I suspect the answer is not 'suspend a thread'. - 我怀疑答案不是'暂停一个帖子'。 It may be that your program design has a problem. 可能是您的程序设计存在问题。

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

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