Linux thread | create terminate recycle detach

1. Thread introduction

Image 1

  • A thread is the smallest unit that participates in system scheduling. It is included in the process and is the actual running unit in the process.

  • Multiple threads can be created in one process, multiple threads can run concurrently, and each thread can perform different tasks.

  • Each thread has its corresponding identifier, called thread ID, and the thread ID is represented by the pthread_t data type.

2. Thread creation

A thread is a lightweight concurrent execution unit that creates and manages threads by calling functions in the pthread library provided by the Linux system.

  • Include the header file:
#include <pthread.h>
  • Define the thread function:

The thread function is the function actually executed by the thread, which can be any function that can be called. The prototype of the thread function is as follows:

void* thread_function(void* arg);

Among them, arg is the parameter passed to the thread function, which can be any type of data. The return value of the thread function is of void* type, and any type of data can be returned.

  • Create thread:

To create a thread, you need to call the pthread_create function. The prototype of this function is as follows:

int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void* (*start_routine)(void*), void* arg);
parameter type description
thread pthread_t * A pointer for storing the new thread identifier
attr const pthread_attr_t * is used to specify the attributes of the new thread, such as stack size, scheduling strategy Etc., it can be NULL, which means to use the default attribute
start_routine void *(*)(void * ) The start function of the new thread needs to return the result of void pointer type, and has a parameter of void pointer type
arg void * The parameter passed to the new thread start function can be NULL
Return value int 0 means success, non-zero means failure, the error code is stored in errno in

Note: After calling the pthread_create() function, the execution of the new thread is performed in parallel with the calling thread, and there is no specific order of execution between them.

Here is an example of creating a thread:

#include 
#include <pthread.h>

void *thread_func(void *arg)
{
    int i;
    for (i = 0; i < 5; i ++ ) {
        printf("This is a thread function, arg=%d, i=%d\\
", *(int *)arg, i);
        sleep(1);
    }
    pthread_exit(NULL);
}

int main()
{
    pthread_t tid; // thread identifier
    int arg = 123; // Arguments passed to the thread function

    // create new thread
    if (pthread_create( &tid, NULL, thread_func, &arg) != 0) {
        printf("Thread creation failed!\\
");
        return 1;
    }

    // Wait for the thread to end and reclaim resources
    if (pthread_join(tid, NULL) != 0) {
        printf("Thread recycling failed!\\
");
        return 1;
    }

    printf("The end of the thread!\\
");
    return 0;
}

Image 3

3. Thread termination

There are two ways to terminate a thread: natural termination and forced termination.

The natural termination of a thread means that the thread automatically exits after performing its work, while the forced termination means that the main thread or other threads explicitly terminate a running thread during the running of the program.

Thread terminates naturally

A thread can terminate naturally by calling the pthread_exit function. The prototype of the pthread_exit function is as follows:

void pthread_exit(void *retval);

The pthread_exit function has no return value, and the parameter retval is the exit status of the thread, which can be obtained through the pthread_join function.

The following is a simple example showing how to use the pthread_exit function to terminate a thread:

#include 
#include <pthread.h>

void *thread_func(void *arg)
{
    int i;
    for (i = 0; i < 5; i ++ ) {
        printf("This is a thread function, i=%d\\
", i);
        sleep(1);
    }
    pthread_exit((void *) "The thread ends normally!");
}

int main()
{
    pthread_t tid; // thread identifier

    // create new thread
    if (pthread_create( & amp;tid, NULL, thread_func, NULL) != 0) {
        printf("Thread creation failed!\\
");
        return 1;
    }

    // Wait for the thread to end and reclaim resources
    void *retval;
    if (pthread_join(tid, & amp;retval) != 0) {
        printf("Thread recycling failed!\\
");
        return 1;
    }

    printf("%s\\
", (char *)retval);
    printf("The end of the thread!\\
");
    return 0;
}

In the above sample program, we call the pthread_exit function in the thread function to terminate the thread and return a string as the exit status.

In the main thread, we use the pthread_join function to wait for the thread to end, and get the exit status of the thread through the pointer retval.

Thread forced termination

In Linux, the forced termination of a thread can be implemented using the pthread_cancel function. The prototype of the pthread_cancel function is as follows:

int pthread_cancel(pthread_t thread);

Among them, the parameter thread is the thread identifier to be canceled. When the pthread_cancel function is called, the canceled thread will exit immediately.

parameter type description
thread pthread_t Identifier of thread to cancel
Return value int 0 means success, non-zero means failure, the error code is stored in errno

Note: Calling the pthread_cancel() function just sends a cancellation request to the specified thread, so that the specified thread exits execution as soon as possible, but does not terminate its execution immediately.

After a thread receives a cancellation request, it can specify how to respond to the request by calling the pthread_setcancelstate() and pthread_setcanceltype() functions, which will not be described here.

The following is a simple example to demonstrate how to use the pthread_cancel function to forcibly terminate a thread:

#include 
#include <pthread.h>

void *thread_func(void *arg)
{
    int i;
    for (i = 0; i < 5; i ++ ) {
        printf("This is a thread function, i=%d\\
", i);
        sleep(1);
    }
    pthread_exit((void *) "The thread ends normally!");
}

int main()
{
    pthread_t tid; // thread identifier

    // create new thread
    if (pthread_create( & amp;tid, NULL, thread_func, NULL) != 0) {
        printf("Thread creation failed!\\
");
        return 1;
    }

    // Wait for a period of time to force the termination of the thread
    sleep(2);
    if (pthread_cancel(tid) != 0) {
        printf("Thread cancellation failed!\\
");
        return 1;
    }

    // Wait for the thread to end and reclaim resources
    void *retval;
    if (pthread_join(tid, & amp;retval) != 0) {
        printf("Thread recycling failed!\\
");
        return 1;
    }

    if (retval == PTHREAD_CANCELED) {
        printf("Thread is canceled!\\
");
    } else {
        printf("%s\\
", (char *)retval);
    }
    printf("The end of the thread!\\
");
    return 0;
}

In the above sample program, the main thread calls the pthread_cancel function to forcibly terminate the child thread.

In the sub-thread function, we use the pthread_exit function to return a string. If the sub-thread ends normally, this string will be printed in the main thread; if the sub-thread is forcibly terminated, Then what will be printed in the main thread will be thread cancelled!.

Image 4

  • not this one
  • I want to say that Thread Recycling has been mentioned several times before, did you forget to tell me
  • I’m sorry, I couldn’t hold back all of a sudden and said it

4. Thread recycling

Use the pthread_join function to wait for the thread to end. The function takes two parameters: a thread identifier and a pointer to the thread’s return value.

int pthread_join(pthread_t thread, void **value_ptr);
parameter type description
thread pthread_t The thread identifier to wait for
value_ptr void ** A pointer used to obtain the exit status of the thread, which can be NULL, indicating that it does not care about exiting Status
Return value int 0 means success, non-zero means failure, error code Save in errno

Note: Calling the pthread_join() function will block the current thread until the specified thread terminates.

If the specified thread has terminated, the function returns immediately without blocking.

In addition, the exit status of the thread can only be obtained if the pthread_join() call succeeds, otherwise the value pointed to by value_ptr is undefined.

Image 5

If other threads do not call the pthread_join() function to reclaim the thread after the thread terminates, the thread will become a zombie thread, which will waste system resources;

The application cannot create a new thread.

Image 6

5. Thread separation

Threads can be detached using the pthread_detach function. The prototype of the pthread_detach function is as follows:

int pthread_detach(pthread_t thread);
parameter type description
thread pthread_t The thread identifier to be detached
Return value int 0 means success, non-zero means failure, the error code is stored in errno

Calling the pthread_detach() function will cause the specified thread to automatically release its related resources when it exits, without requiring other threads to call the pthread_join() function to wait for its exit and reclaim resources .

Calling pthread_detach() will return an error if the specified thread has already been detached or exited.

The following is a simple example to demonstrate how to use the pthread_detach function to detach a thread:

#include 
#include <pthread.h>

void *thread_func(void *arg)
{
    int i;
    for (i = 0; i < 5; i ++ ) {
        printf("This is a thread function, i=%d\\
", i);
        sleep(1);
    }
    pthread_exit((void *) "The thread ends normally!");
}

int main()
{
    pthread_t tid; // thread identifier

    // create new thread
    if (pthread_create( & amp;tid, NULL, thread_func, NULL) != 0) {
        printf("Thread creation failed!\\
");
        return 1;
    }

    // detach thread
    if (pthread_detach(tid) != 0) {
        printf("Thread separation failed!\\
");
        return 1;
    }

    printf("The thread has been separated, resources will be recovered automatically!\\
");

    // end of program
    return 0;
}

In the above sample program, we detach the thread immediately after creating the thread, and print a prompt message to tell the user that the thread has been detached, and resources will be automatically recovered when exiting.

When running the above program, you can see the following output:

The thread has been separated and resources will be automatically recovered!
This is the thread function, i=0
This is the thread function, i=1
This is the thread function, i=2
This is the thread function, i=3
This is the thread function, i=4

As you can see, the program creates a new thread and immediately detaches it. In the child thread, we print 5 strings with 1 second interval between each string.

In the main thread, we print a message to tell the user that the thread has been detached and resources will be automatically reclaimed when it exits. Finally, the program ends normally without calling the pthread_join function.

Summary

We have introduced the basic operations such as the creation, termination, recycling, and separation of Linux threads.

In actual programming, we may also need to use some other functions and techniques, such as mutexes, condition variables, semaphores, read-write locks, etc.

Picture 7

If you want to know what will happen next, please listen to the next chapter!

Welcome everyone Like ?Favorite Comment, if there is any mistake, please leave a message to correct me, thank you very much!