【问题标题】:How to suspend and resume a POSIX thread in C++?如何在 C++ 中暂停和恢复 POSIX 线程?
【发布时间】: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。我已适当地重新标记和重新命名。

标签: c++ multithreading pthreads resume


【解决方案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;
}

【讨论】:

    猜你喜欢
    • 2011-08-08
    • 2010-11-06
    • 2020-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多