Linux---Multithreaded

Thread

What is a thread

  • In a program, an execution flow is a thread, in other words, a thread is the internal control sequence of the process. (In process, we say that a running program is a process).
  • Under Linux, threads are calledLightweight process, Because the thread is realized by the pcb simulation of the process under Linux, the threads in the same process share most of the resources of the process.
  • A process is a collective name (thread group) of all threads in the process, and when allocating resources, the entire thread group (that is, process) is allocated. The process is equivalent to a factory, and the threads are the workers in the factory.
  • The process is the basic unit of resource allocation, and the thread is the basic unit of CPU scheduling. Process on the left
    From the perspective of the kernel, threads and processes are the same and have their own pcbs, but pcb points to the same virtual address space in all threads in the same process.

Insert picture description here
The process and the thread are in a containment relationship, and there is at least one thread in the process.

Sharing and uniqueness of thread resources

Since a process has multiple threads, it means that a process has multiple execution streams, and these execution streams access the same virtual address space at the same time. How is it possible that there will be no call stack confusion or data ambiguity?
Not all resources of a thread are shared, and some of its resources are unique.

Share resource

  • Code segment and data segment: A thread is an execution flow of a process, sharing the code and data of the program.
  • Signal processing method: When the thread encounters an exception, the processing method should be the same.
  • IO information:
  • Working path:
  • User ID and user group ID:
  • Priority scheduling

Unique resources

  • Thread ID: Each thread has its own pcb.
  • Call stack: Each thread has its own call stack to avoid call stack confusion.
  • Register: Because each thread is an independent execution flow.
  • Signal shielding word: shield the signal you want to shield.

Advantages of threads

  • Creating a thread is less expensive than creating a process. The creation process needs to create pcb, map virtual address space for pcb, etc. To create a thread, you only need to create a pcb.
  • The thread switching scheduling cost in the same process is lower
  • Communication between threads is more flexible and convenient. In addition to process communication, threads can also communicate through global variables and function parameter transfer.
  • The resource occupied by threads is smaller than that of processes.

Multithreading and multiprocessing

When there is only one process, if you want to perform addition, deletion, modification, and check, you need to execute it in 4 steps.
Insert picture description here
When there are multiple processes, perform addition, deletion, modification, and checking, and they can be synchronized.
Insert picture description here
When multi-threaded execution.
Insert picture description here

Multi-threaded processing idea: In a running program, there are multiple execution streams, each of which completes a functional module.

The difference between multithreading and multiprocessing

Advantages of threads:

  • The cost of creation and destruction is lower, and there is no need to allocate virtual address space when creating threads.
  • The cost of switching scheduling between threads in the same process is lower.
  • The thread communication method is more flexible. On the basis of process communication, it can also participate in global variable communication through function transmission.
    Advantages of the process:
  • The robustness is higher, and some operations have an effect on the entire process, for example: the system calls exit.

Thread creation

int pthread_create(pthread_t *tid,pthread_attr_t *attr,void* (*thread_routine)(void *arg),void *arg);
tid:输出型参数,用于向用户返回线程id
attr:设置线程属性,同常情况下NULL
thread_routine:线程的入口函数
arg:通过线程入口函数的参数传递给线程的数据
返回值:成功返回0,失败返回非0

ps -L: View lightweight process information.
Insert picture description here
LWP: The pid of the lightweight process is actually the pid of the pcb.
The process id seen outside is actually tgid (thread group id), the thread group id is equal to the lightweight id of the main thread in the process

When a thread is created, a relatively independent space will be opened up in the virtual address space of the process as the address space of the thread. This space contains the user's description of the thread and realizes the operation of the thread. After the creation is successful, this space will be returned. To the user. The user can operate the thread through the first address of the memory, so the first address of the thread address space returned is the operation handle of the thread, which is the tid of the pthread_create function.
The thread address space is part of the process address space
Insert picture description here

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

void *thread_func(void *arg) 
{
    
               
        printf("这个线程Id:%p\n",pthread_self());
        return NULL;
}          

int main()    
{
    
         
        pthread_t tid;
        char *buf = "创建线程\n";
        int ret = pthread_create(&tid,NULL,thread_func,(void*)buf);
        if(ret!=0)
        {
    
    
                printf("创建失败\n");
                return 0;
        } 
        printf("普通线程Id:%p\n",tid);
        printf("主线程Id:%p\n",getpid());
        return 0;
}

Note: Since the pthread_create interface is a library function, you need to add a static library when compiling
Solution

Thread termination

Substance: exit a thread

Exit method

  • Active exit: return in thread entry function. (The return in the main function is used to exit the process rather than the thread)
    void pthread_exit(void *retval); exit the calling thread; retval: exit return value.
  • Passive exit:
    int pthreadd_cancel(pthread_t thread); cancel a thread, thread: the id of the thread to be canceled

Call pthread_exit function in the main thread, you can exit the main thread, but will not exit the process, process exit is when all threads in the process exit, the process will exit.

Thread waiting

Wait for a specified thread to exit, get the return value of the exited thread, and allow the operating system to reclaim the resources occupied by the thread.
However, not all threads need to be waited.
The thread has an attribute default value: joinable, the thread in the joinable attribute will not automatically release resources after exiting, and other thread processes need to wait for processing.

Essence
Get the resources after the thread exits and release the resources.

How to wait for processing:

int pthread_join(pthread_t tid,void **retval);
tid:用于指定要等待的线程
retval:输出型参数,返回线程退出的返回值

The pthread_join function waits for a specified thread to exit. If the specified thread does not exit, it will wait forever. (Blocking function)

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

void *Join_func(void *arg)
{
    
    
	printf("Normal thrread will eixt\n");
	sleep(5);
	char *buf = "Normal thread eixt\n";
	return buf;
}

int main()
{
    
    
     pthread_t tid;
     int ret = pthread_create(&tid,NULL,Join_func,NULL);
     if(ret!=0)
     {
    
    
             printf("thread create failed\n");
             return -1;
     }
     printf("Main thread waiting Normal thread to eixt\n");
     char *retval = NULL;
	 pthread_join(tid,(void**)&retval);
	 printf("retval:%s\n",retval);
	 return 0;
}

Thread separation

The reason is
because the thread in the joinable attribute will not automatically release the resources after exiting, so the thread needs to wait, but in the thread waiting, it will need to wait for the return value of the thread to exit, and then wait for the thread to exit. It will cost other threads when you don’t want to consume it. For other resources, thread separation is required.

Essence
Set the thread attribute, set joinable to detach, after the thread with the detach attribute exits, the resource will be released automatically, and this thread does not need to be waited.

How to separate a thread

int pthread_detach(pthread_t tid);//分离一个指定线程,设置该线程的属性为detach
tid:用于指定线程

This function is a non-blocking function. The essence of separating a thread is to set a thread attribute, so this library function can be called anywhere.

void detach_fun(void *arg)
{
    
    
	pthread_detach(pthread_self());//分离自己
}

Thread ID

Each thread has a unique identifier, called the thread ID, which is returned to the caller.

  • Checking the ID
    Pthread_self(void)The return value of this function is of type Pthread_t, and we can get the thread ID according to the return value of this function.
  • Judge whether the thread IDs are equal and
    Pthread_equal(pthread_t p1,pthread_t p2);p1 and p2 are equal, then return non-zero, and if they are equal, return zero.

Guess you like

Origin blog.csdn.net/qq_42708024/article/details/104428113