How to stop a running pthread thread?

2020-02-11 05:49发布

How can I exit or stop a thread immediately?

How can I make it stop immediately when the user enters an answer? I want it to reset for every question.

Here's my code where threading is involved

int q1() {
    int timer_start;
    char ans[] = "lol";
    char user_ans[50];
    timer_start = pthread_create( &xtimer,NULL,(void*)timer_func,(void*)NULL);
    printf("What is the capital city of Peru?\n");

    while(limit){
        scanf("%s",user_ans);
        if(limit)
        {
             if(!strcmp(user_ans, ans))
              {

               // printf("YAY!\n");
                score++;
               // q2();

            }
            else
            {
                game_over();
            }
        }
    }
}

4条回答
等我变得足够好
2楼-- · 2020-02-11 06:03

Based on your code I can give a simple answer:

In this case do not use threads at all.

You do not need them. Store the start time, let the user answer, check the time again after user gives an answer.

{
  time_t startTimeSec = time(NULL);

  // answering

  time_t endTimeSec = time(NULL);
  time_t timeTakenSec = endTime-startTime;
  if (timeTaken > 10) { 
    // do your thing
  }
}

To answer your question:

You should use a mutex-protected or volatile variable to asynchronously communicate between threads. Set that variable from one thread and check it in another. Then reset its value and repeat. A simple snippet:

int stopIssued = 0;
pthread_mutex_t stopMutex;

int getStopIssued(void) {
  int ret = 0;
  pthread_mutex_lock(&stopMutex);
  ret = stopIssued;
  pthread_mutex_unlock(&stopMutex);
  return ret;
}

void setStopIssued(int val) {
  pthread_mutex_lock(&stopMutex);
  stopIssued = val;
  pthread_mutex_unlock(&stopMutex);
}

Using pthread_cancel() is an option, but I would not suggest doing it. You will have to check the threads state after this call returns, since pthread_cancel() does not wait for the actual thread stop. And, which to me is even more important, I consider using it ugly.

查看更多
别忘想泡老子
3楼-- · 2020-02-11 06:08

@Naruil's suggestion to call pthread_cancel() is pretty much the best solution i found, but it won't work if you didn't do the following things.

According to the man-page of pthread_cancel the pthread_cancelibility depend on two thing

  1. thread_cancel_state.
  2. thread_cancel_type.

thread_cancel_state is PTHREAD_CANCEL_ENABLE by default, so our main concern is about the thread_cancel_type, it's default value is type PTHREAD_CANCEL_DEFFERED but we need PTHREAD_CANCEL_ASYNCHRONOUS to set on that thread, which we wan't to cancel.

Following an example given::

#include <stdio.h>
#include <pthread.h>

void *thread_runner(void* arg)
{   
    //catch the pthread_object as argument
    pthread_t obj = *((pthread_t*)arg);

    //ENABLING THE CANCEL FUNCTIONALITY
    int prevType;
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &prevType);

    int i=0;
    for( ; i < 11 ; i++)//1 - > 10
    {
        if(i == 5)
            pthread_cancel(obj);
        else
            printf("count -- %d", i);
    }
    printf("done");
}

int main(int argc, char *argv[])
{
    pthread_t obj;

    pthread_create(&obj, NULL, thread_runner, (void*)&obj);

    pthread_join(obj, NULL);

    return 0;
}

run it using gcc filename.c -lpthread and output the following:: count -- 0 count -- 1 count -- 2 count -- 3 count -- 4

note that the done is never printed because the thread was canceled when the i became 5 & the running thread was canceled. Special thanks @Naruil for the "pthread_cancel" suggestion.

查看更多
家丑人穷心不美
4楼-- · 2020-02-11 06:14

You can simply call pthread_cancel on that thread to exit it. And you can send SIGSTOP/SIGCONT signal via pthread_kill to stop/restart it.


But if all you want is a timer, why must you thread?

查看更多
够拽才男人
5楼-- · 2020-02-11 06:25

Using methods to stop a thread is a brute way. You should rather politely ask the thread to stop by signalling. Thereby the thread will have an option to tidy after itself e.g. if it has allocated memory, which it will not have any opportunity to do if the thread is cancelled.

The method is relatively simple and comprises no OS signalling:

define a thread state variable or structure outside the thread. Point to it at the pthread_create and dereference the state variable in the thread.

int thread_state = 0; // 0: normal, -1: stop thread, 1: do something

static void *thread_1 (void *arg)
{
   int* pthread_state = arg;
   ... // initialize the thread locals
   while(1)
   {
      switch( *pthread_state )
      {
      case 0: // normal thread loop
         ...
         break;
      case -1:
         ... // tidy or whatever is necessary
         pthread_exit(0); // exit the thread signalling normal return
         break;
      case 1: //
         ... // do something special
         break;
      }
   }
}

pthread_create (&t_1, NULL, thread_1, (void*)&thread_state);

...

thread_state = -1; // signal to the thread to stop

// maybe use pthread_exit(0) to exit main.
// this will leave the threads running until they have finished tidy etc.

It is even possible to communicate with the thread using a structure provided that it is simple 'atomic' variables or a simple handshake mechanism is established. Otherwise it may be necessary to use mutex. Use pthread_join to wait for threads to terminate.

查看更多
登录 后发表回答