Thread thread learning (3) Understand the pthread_cancel() function in Linux threads

Table of contents

1. Understand the pthread_cancel() function

2. Basic example of using pthread_cancel() function

3. An advanced example of using the pthread_cancel() function to cancel a thread

(1) Precautions

(2) Advanced example

Fourth, the extension of the pthread_cancel() function

(1) How to define the cancellation point:

(2) The pthread_cancel() function needs to be operated carefully, following the following points:

Four. Summary


        In the Linux system, a thread is a lightweight execution unit that allows a program to execute multiple tasks simultaneously within the same process. However, in some cases, we may need to cancel the execution of a thread while the program is running. This article will introduce the pthread_cancel() function, which is used to cancel an executing thread, and illustrate its use through examples.

1. Understand the pthread_cancel() function

        The pthread_cancel() function is a function used to cancel thread execution in the Linux system, and its prototype is as follows:

#include <pthread.h>

int pthread_cancel(pthread_t thread);

        This function accepts a parameter thread of type pthread_t, which is used to specify the thread to be canceled. The function returns 0 when the thread is successfully canceled; otherwise, it returns a non-zero value. After calling the pthread_cancel() function, the target thread will receive a cancellation request, and then exit the thread execution at an appropriate time.

2. Basic example of using pthread_cancel() function

        The following uses an example to demonstrate how to use the pthread_cancel() function to cancel a thread.

#include <stdio.h>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>

void* thread_func(void* arg)
{
    int count = 0;
     while (1) {
        printf("Thread is running, count: %d\n", count);
        count++;
        sleep(1);
    }
    // 检查取消请求
	pthread_testcancel();
	printf("Thread cancellation requested. Exiting...\n");
	pthread_exit(NULL);
    return NULL;
}
int main()
{
    pthread_t thread;
    // 创建线程
    pthread_create(&thread, NULL, thread_func, NULL);
    // 等待一段时间
    sleep(3);
    // 取消线程执行
    pthread_cancel(thread);
    // 等待线程退出
    pthread_join(thread, NULL);
    printf("Thread canceled successfully.\n");
    return 0;
}

The result of the operation is as follows:

开始运行...

Thread is running, count: 0
Thread is running, count: 1
Thread is running, count: 2
Thread is running, count: 3
Thread canceled successfully.

运行结束。

The main logic of the code is as follows:

  1. In main()the function, we create a child thread threadand set its execution function to thread_func.

  2. thread_funcIt is the execution function of the child thread. In this function, we use a loop to simulate the work of the thread, printing the count value every second count. This loop will execute until a cancel request is received.

  3. In the main thread, we use to sleep(3)wait for 3 seconds, and then call pthread_cancel(thread)to send a cancel request to the child thread.

  4. Next, we use pthread_join(thread, NULL)to wait for the child thread to exit. In this way, the main thread will block until the execution of the child thread is completed.

  5. Finally, the main thread outputs "Thread canceled successfully." indicating that the thread was canceled successfully.

        When running this code, you will see that the child thread prints the count value every second, and the main thread cancels the execution of the child thread after waiting for 3 seconds. After the child thread receives the cancel request, it outputs the corresponding message and exits. Finally, the main thread outputs a message that the thread was canceled successfully.

        Please note that using pthread_cancel()the function to cancel a thread requires careful handling to ensure that the thread completes the necessary cleanup work before being canceled to avoid resource leaks or data inconsistencies. In this example, we use in the child thread pthread_testcancel()to check for cancellation requests to ensure that the thread exits at the point of cancellation.

3. An advanced example of using the pthread_cancel() function to cancel a thread

(1) Precautions

Before using the pthread_cancel() function to cancel a thread, you need to pay attention to the following points:

1. Ensure that the thread can be cancelled: the thread needs to run in a cancelable state, that is, it needs to set the thread’s cancellation status to cancelable when creating the thread, which can be achieved in the following ways:

// 设置线程的取消状态为可取消
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

2. Set the cancellation type: The cancellation type of the thread determines the behavior of the thread when it is canceled. The cancellation type can be set in the following ways:

// 设置线程的取消类型为延迟取消
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

Common cancellation types are PTHREAD_CANCEL_DEFERRED (thread cancellation takes effect at the next cancellation point) and PTHREAD_CANCEL_ASYNCHRONOUS (cancel thread immediately).

3. Define a cancellation point: A cancellation point is a location in a program where a thread can be canceled. Common cancellation points include threads blocked in I/O operations, sleeping, waiting for locks, etc.

Once the thread meets the above requirements, we can use the pthread_cancel() function to cancel the thread. Call the pthread_cancel() function in the main thread and pass the thread identifier to be canceled as a parameter. For example:

// 其中thread_id为要取消的线程的标识符。
pthread_cancel(thread_id);

(2) Advanced example

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>

void* thread_function(void* arg) {
    printf("子线程开始执行\n");   
    // 设置线程的取消状态为可取消
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 
    // 设置线程的取消类型为延迟取消
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
    while(1) {
        printf("子线程执行中...\n");
        sleep(1);
    }   
    printf("子线程执行完毕\n");
    pthread_exit(NULL);
}

int main() {
    pthread_t thread;
    int res;  
    // 创建子线程
    res = pthread_create(&thread, NULL, thread_function, NULL);
    if (res != 0) {
        perror("线程创建失败");
        exit(EXIT_FAILURE);
    }   
    sleep(3);   
    // 取消子线程
    res = pthread_cancel(thread);
    if (res != 0) {
        perror("线程取消失败");
        exit(EXIT_FAILURE);
    }  
    // 等待子线程结束
    res = pthread_join(thread, NULL);
    if (res != 0) {
        perror("线程等待失败");
        exit(EXIT_FAILURE);
    }  
    printf("主线程执行完毕\n");  
    return 0;
}

The result of the operation is as follows:

开始运行...

子线程开始执行
子线程执行中...
子线程执行中...
子线程执行中...
子线程执行中...
主线程执行完毕

运行结束。

        In this sample code, we create a sub-thread, and print information in a loop in the sub-thread. After the main thread waits for 3 seconds, it pthread_cancel()cancels the execution of the child thread by calling the function. The child thread will check whether a cancellation request is received in each cycle. Since we set the cancellation type to delayed cancellation, the child thread will cancel at the next cancellation point.

        Note that in the child thread, we use to pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)set the thread's cancellation status to cancelable, and use to pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL)set the thread's cancellation type to delayed cancellation.

        Run the above code, you will see that the sub-thread starts to execute and prints information continuously, and after calling the function in the main thread, the pthread_cancel()sub-thread will be canceled at the next cancellation point, and output "sub-thread execution completed". Finally, the main thread outputs "main thread execution completed", and the program ends normally.

        Note that the actual cancellation point depends on the specifics of the code, for example there may be a cancellation point when blocking an I/O operation or calling a specific function. In a practical application, please ensure that there are appropriate cancellation points in your code so that you can respond to cancellation requests in a timely manner.

Fourth, the extension of the pthread_cancel() function

(1) How to define the cancellation point:

A cancellation point is a point in a program where a thread can be canceled. In order to define the cancellation point, we can use the following method:

  1. Blocking I/O operation: When performing blocking I/O operations, the thread will wait for the I/O to complete. At this time, this waiting process can be used as a cancellation point. For example, when using functions such as read(), write(), or select() for file reading and writing or network communication, these functions can be used as cancellation points while waiting for I/O to complete.

  2. Thread sleep: When a thread calls a sleep function (such as sleep(), usleep()), the thread will enter the sleep state, and this sleep process can be used as a cancellation point.

  3. Waiting for a mutex: When a thread is waiting for a mutex, the process of waiting for the mutex can be set as a cancellation point. During the waiting period, the thread is temporarily suspended, waiting for other threads to release the mutex.

  4. Waiting for a condition variable: When a thread is waiting for a condition variable to satisfy a condition, the process of waiting for the condition variable can be set as a cancellation point. During the waiting period, the thread will temporarily hang, waiting for other threads to send signals to meet the conditions.

  5. pthread_testcancel() function: This function is a special way to define the cancellation point. You can manually insert the pthread_testcancel() function in the code to detect the cancellation request. If there is a cancellation request, this function will cancel the thread immediately.

When using cancellation points, you need to pay attention to the following points:

  • The setting of the cancellation point should be reasonable to ensure thread safety and data consistency. The location of the cancellation point should be in a suitable place, avoid setting the cancellation point in the key code segment or critical section.

  • The location of the cancellation point should meet the requirements of the business logic, and avoid setting the cancellation point before or after a key operation, so as not to cause data inconsistency or program logic errors.

  • When designing a multi-threaded program, the location of the cancellation point and the cancellation operation should be fully considered to ensure the correctness and maintainability of the program.

By setting the cancellation point reasonably, we can cancel the thread when needed to achieve more flexible and controllable multi-threaded programming.

(2) The pthread_cancel() function needs to be operated carefully, following the following points:

Use pthread_cancel() function requires careful operation, follow the following points:

  1. When designing a thread, you should consider the cancellation of the thread, and set the cancellation point reasonably to ensure the safety and data consistency of the thread.

  2. When canceling a thread, you should ensure that the thread has completed the necessary cleanup work before being canceled, such as releasing dynamically allocated memory, closing open files, and so on.

  3. Note the return value that handles thread cancellation. If the pthread_cancel() function returns 0, it means that the cancellation request was successfully sent, but it does not mean that the thread terminates immediately. You can use the pthread_join() function to wait for the thread to terminate and get the return value of the thread.

Four. Summary

         This article provides an in-depth introduction to the pthread_cancel() function of Linux threads, which can be used to cancel an executing thread. When using the pthread_cancel() function, it is necessary to properly set the cancellation status and cancellation type of the thread, and ensure that the thread completes the necessary cleanup work before cancellation. At the same time, the return value of the cancel operation needs to be properly handled. Reasonable use of the pthread_cancel() function can help us achieve more flexible and controllable multi-threaded programming.

 Note sharing, if there is a mistake, thank you for your advice;

Guess you like

Origin blog.csdn.net/qq_50635297/article/details/130719162