【问题标题】:How do I make a thread stop another thread?如何让一个线程停止另一个线程?
【发布时间】:2019-05-12 17:27:41
【问题描述】:

我基本上刚刚发现存在多线程编程,并且我在盲目地玩弄这个概念很有趣。

我正在尝试做的是一个计时器,它每秒动态检查一次,同时用户继续以某种形式与程序进行交互。

这是我目前能够完成的:

void* timer (void* threadToStop)
{
    pthread_t* threadName = threadToStop;

    time_t startTime = time(NULL);
    time_t currentTime;
    int elapsedTime;
    int remainingTime;

    do {

        if (currentTime != time(NULL)) 
        {
            currentTime = time(NULL);
            elapsedTime = currentTime - startTime;
            remainingTime = 10 - elapsedTime;
            printf("%d ", remainingTime);
            fflush(stdout);
        }

    } while (remainingTime > 0);

    pthread_cancel(*threadName);

    return NULL;
}

void* func (void* vargp)
{
    getchar();

    return NULL;
}

int main(void)
{

    pthread_t funcId;
    pthread_create(&funcId, NULL, func, NULL);

    pthread_t timerId;
    pthread_create(&timerId, NULL, timer, &funcId);

    pthread_join(funcId, NULL); 

    return EXIT_SUCCESS;
}

从两个不同的函数创建两个线程并开始同时运行。

"func" 只是一个要求用户输入字符的虚拟函数。这只是在计时器在后台运行时让用户与程序交互的一种方式。

"timer" 是不言自明的:它是每秒启动和更新计时器的函数。当这个线程被创建时,它也会得到func 的线程ID 作为参数。时间到了,我调用pthread_cancel 函数以停止使用其id 的func 的线程。

这个程序大部分时间都在工作:当我能够在控制台中输入字符时,计时器继续运行,当我按下回车键时,pthread_join 函数启动并且主要函数到达结束。但是,当计时器用完时,func 线程不会被取消,我很难弄清楚原因。

【问题讨论】:

  • 请不要在给出 cmets 和/或答案后更改问题,因为这可能会使它们难以理解。而是用添加来更新您的问题。不过我会回滚你的最后一次更改。
  • 对不起,这里还是个新手。

标签: c multithreading pthreads


【解决方案1】:

代码在使用之前错过了初始化currentTime

  time_t currentTime;
  int elapsedTime;
  int remainingTime;

  do {

    if (currentTime != time(NULL)) 

只有在通过或“坐在”所谓的取消点时,线程才会被取消。

getchar() 不一定是取消点。

POSIX 线程的强制和可选取消点列表是here


为了阐明真正发生的替换:

  pthread_cancel(...);

作者:

  errno = pthread_cancel(...);
  if (0 != errno)
  {
    perror("pthread_cancel() failed");
  }

【讨论】:

  • 谢谢,我真的没有注意到这个错误。顺便问一下,这是否意味着只有在正确的条件下才能停止线程?有没有办法做我想做的事情(当时间结束时无条件地突然停止任何可能的线程)?
  • "这是否意味着只有在正确的条件下才能停止线程" 是的。尽管如此,人们还是应该尝试以一种完全不需要使用pthread_cancel() 的方式来设计代码。在像您这样更复杂的场景中,由于异步的性质,在尝试取消线程时很容易遇到任何类型的麻烦。人们几乎永远不会真正知道线程“刚刚结束”的时间和地点,从而使系统处于未明确定义的状态或至少是未知状态。
  • 没有其他方法可以解决这个问题吗?我曾想过某种标志,但是当线程位于 getchar 之类的函数上时,我仍然无法检查该标志。它不会在任何时候被实时检查。这就是我想到一个更激烈的线程取消解决方案的原因。
  • @Gian:要让阻塞函数返回,一种常见的方法是向阻塞线程发送信号。然后该函数通常会返回指示错误并将errno 设置为EINTR。信号使多线程变得更加有趣。 ;)
  • 谢谢你的提示,我会调查的!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多