如何在 C++ 中暂停和恢复 POSIX 线程?

Posted

技术标签:

【中文标题】如何在 C++ 中暂停和恢复 POSIX 线程?【英文标题】:How to suspend and resume a POSIX thread in C++? 【发布时间】:2018-06-12 13:45:31 【问题描述】:

据我所知,突然创建和终止线程 每次都使用 pthread_kill() 不是一个好方法,所以我要去 使用 thread1.suspend() 和线程的挂起和恢复方法 thread1.resume(),随时需要。如何做/实现这个?

以下 LED 闪烁代码供参考。在thread1.start() 期间,使用suspended = false; 创建线程正在继续,因为它卡在了一个while 循环中。 调用thread1.suspend()没有效果。

#define on 1
#define off 0
void gpio_write(int fd, int value);
void* led_Flash(void* args);


class PThread 
    public:

    pthread_t threadID;
    bool suspended;
    int fd;
    pthread_mutex_t m_SuspendMutex;
    pthread_cond_t m_ResumeCond;

    void start() 
        suspended = false;
        pthread_create(&threadID, NULL, led_Flash, (void*)this );
    

    PThread(int fd1)  this->fd=fd1; 
    ~PThread()  

    void suspend() 
        pthread_mutex_lock(&m_SuspendMutex);
        suspended = true;
        printf("suspended\n");
        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;
        printf("Resumed\n");
        pthread_cond_signal(&m_ResumeCond);
        pthread_mutex_unlock(&m_SuspendMutex);
    
;

void* led_Flash(void* args)
  
    PThread* pt= (PThread*) args;
    int ret=0;
    int fd= pt->fd;

       while(pt->suspended == false)
        
        gpio_write(fd,on);
        usleep(1); 
        gpio_write(fd,off);
        usleep(1); 
           


return NULL;



int main()

    int fd1=1,fd2=2, fd3=3;

    class PThread redLED(fd1);
    class PThread amberLED(fd2);
    class PThread greenLED(fd3);

    redLED.start();
    amberLED.start();
    greenLED.start();

    sleep(1);
    redLED.suspend();

return 0;

有人能帮帮我吗?

【问题讨论】:

杀死/暂停/恢复所有坏的。尽量不要从用户代码中做任何这些事情。尽量安排线程被创建的唯一时间是在进程启动时,线程被杀死的唯一时间是进程终止。 pt->suspended 既不是易失的也不是原子的。所以我的猜测是编译器将while(pt->suspended == false) ... 优化为if (pt->suspended == false) again: ...; goto again; 。如果变量是从信号处理程序更改的,那么 Volatile 将是正确的。对于多线程,最好使用 atomic。 "调用 thread1.suspend() 无效。"通过阅读代码,我希望红色 LED 继续闪烁(参见前面的评论),并且主线程只是卡在那里等待恢复条件。那是对的吗?您是希望挂起阻塞主线程还是希望 led_Flash 停止直到恢复?目前 led_Flash 将简单地退出线程,如果它看到pt->suspended == true,就没有任何东西可以恢复。 您可以用单个 POSIX sem_t 替换您的 pthread_mutex_tpthread_cond_t。然后你的suspend() 变成一个简单的sem_wait(),而resume() 是一个sem_post()。因为你真正在做的只是阻塞。 该代码本质上是 C++ 代码,因为 class PThread … ; 及其内容不是有效的 C。我已适当地重新标记和重新命名。 【参考方案1】:

对上述代码稍作修改后,似乎可以正常工作了。感谢大佬指出上述代码的问题,改动如下。

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<iostream>
#define on 1
#define off 0
void gpio_write(int fd, int value);
void* led_Flash(void* args);


class PThread 
    public:

    pthread_t threadID;
    volatile int suspended;
    int fd;
    pthread_mutex_t lock;
    PThread(int fd1)
      
        this->fd=fd1; 
        this->suspended =1;  //Initial state: suspend blinking untill resume call 
        pthread_mutex_init(&this->lock,NULL); 
        pthread_create(&this->threadID, NULL, led_Flash, (void*)this );

    
    ~PThread() 
     
      pthread_join(this->threadID , NULL);
      pthread_mutex_destroy(&this->lock);
    

    void suspendBlink() 
        pthread_mutex_lock(&this->lock);
        this->suspended = 1;
        pthread_mutex_unlock(&this->lock);
    

    void resumeBlink() 
        pthread_mutex_lock(&this->lock);
        this->suspended = 0;
        pthread_mutex_unlock(&this->lock);
    
;

void gpio_write(int fd, int value)

if(value!=0)
 printf("%d: on\n", fd);
else
 printf("%d: off\n", fd);



void* led_Flash(void* args)
  
    PThread* pt= (PThread*) args;
    int fd= pt->fd;

    while(1)
    
    if(!(pt->suspended))
        
        gpio_write(fd,on);
        usleep(1); 
        gpio_write(fd,off);
        usleep(1);
        
   


return NULL;



int main()

   //Create threads with Initial state: suspend/stop blinking untill resume call 
    class PThread redLED(1);
    class PThread amberLED(2);
    class PThread greenLED(3);

    // Start blinking
    redLED.resumeBlink();
    amberLED.resumeBlink();
    greenLED.resumeBlink();
    sleep(5);

    // suspend/stop blinking
    amberLED.suspendBlink();

    sleep(5);

    redLED.suspendBlink();

    sleep(5);

    amberLED.suspendBlink();

    sleep(5);     

    redLED.resumeBlink();  


pthread_exit(NULL);

return 0;

【讨论】:

以上是关于如何在 C++ 中暂停和恢复 POSIX 线程?的主要内容,如果未能解决你的问题,请参考以下文章

在c中暂停posix线程特定时间间隔的问题

如何使用 threading 模块暂停和恢复线程?

如何暂停线程池、运行函数和恢复?

暂停和恢复 Grand Central Dispatch 线程

c++中的Posix线程

Linux C++ 用户空间应用程序实时睡眠功能(POSIX、Raspberry Pi)