如何从主线程唤醒睡眠线程?

时间:2014-05-26 23:36:05

标签: c multithreading pthreads posix

我有一个捕获程序,另外捕获数据并将其写入文件也会打印一些统计信息。打印统计信息的函数

static void report(void)
{
         /*Print statistics*/
}
使用每秒过期的ALARM大致每秒调用

。所以程序就像

void capture_program()
{
       pthread_t report_thread

            while()
            {
                     if(pthread_create(&report_thread,NULL,report,NULL)){
                            fprintf(stderr,"Error creating reporting thread! \n");
                     }

                     /*
                        Capturing code
                        --------------
                        --------------
                      */
                      if(doreport)
                             /*wakeup the sleeping thread.*/

            }
}

void *report(void *param)
{
       //access some register from hardware
       //sleep for a second 

}

计时器到期时设置doreport标志。如果设置了此标志,则调用report()清除标志。

当计时器在主线程中关闭时,如何唤醒睡眠线程(运行report())?

3 个答案:

答案 0 :(得分:5)

您可以使用sigwait来休眠线程,然后通过pthread_kill发出该线程的信号。杀死听起来不错,但它并没有杀死线程,它会发出信号。这种方法非常快。它比条件变量快得多。我不确定它是否更容易,更难,更安全或更危险,但我们需要性能,所以我们走这条路。

在某处的启动代码中

sigemptyset(&fSigSet);
sigaddset(&fSigSet, SIGUSR1);
sigaddset(&fSigSet, SIGSEGV);

要睡觉,线程会这样做:

int nSig;
sigwait(&fSigSet, &nSig);

唤醒(从任何其他线程完成)

pthread_kill(pThread, SIGUSR1);

或者醒来你可以这样做:

tgkill(nPid, nTid, SIGUSR1);

我们的代码在创建子线程之前在主线程上调用它。我不确定为什么要这样做。

pthread_sigmask(SIG_BLOCK, &fSigSet, NULL);

答案 1 :(得分:4)

  

如何唤醒睡眠线程(运行报告())   计时器在主线程中关闭?

我认为condition variable是您正在寻找的机制。在条件变量上有报告线程块,并且只要您希望报告线程被唤醒,主线程就会发出条件变量(请参阅链接以获取更详细的说明)。

答案 2 :(得分:3)

在对UDP聊天服务器进行编码时,我遇到了类似的问题:有一个线程_1仅在警报中断(超时以查看客户端是否仍然存在)或另一个线程_2(此线程满足客户端请求)到达时才起作用。我所做的就是让该线程_1进入睡眠状态(sleep(n*TICK_TIMER),其中TICK_TIMER是警报到期值,n是大于1的整数),然后用SIGALRM信号唤醒该线程。 See sleep() doc

警报处理程序(要使用它,您必须将其初始化:“ signal(SIGALRM,tick_handler); alarm(5);“)

void tick_handler(){tick_flag++; alarm(5); }

在发生超时时将发送SIGALRM

从另一个线程_2唤醒此睡眠线程_1的命令是:

    pthread_kill(X,SIGALRM);

其中X是pthread_t类型。如果您的thread_1是您的主线程,则可以通过pthread_t X = pthread_self();

来获取此号码