thread thread waiting

difference between thread and process

In the operating system, a process is the smallest unit that provides program running resources, and a thread is the smallest unit that schedules these resources, also known as the execution flow of the process.
When a process is running, its address space is independent of another process. That is to say, their resources are unique, and a process cannot see the resources of another process under normal circumstances (except for process communication)

And multiple threads within a process, they run in an address space range, so they can see and share the resources provided by the process

So the operating system creates a process, assigning it at least one thread (execution flow)

Threads under Linux

There is no thread data structure provided under Linux, but we know that the PCB allocated by the operating system to a process is the structure of task_struct;

But in fact, the process under the Linux system is a lightweight process (LWP), and the key fields of its task_struct structure are as follows

{
 pid_t pid;
 pid_t tgid;

 struct task_struct *group_leader;

 struct list_ehad thread_group;

}

Among them, pid is actually the ID number of the execution flow, that is, the ID number of the thread,
and tgid is the ID number shared by the execution flow of this group, which actually reflects the ID number of a process.

When we call the system call getpid(); what we return is actually tgid (the ID shared by the execution flow)

When there is only one execution flow in a process, obviously the value of pid is equal to tgid

It will give us the illusion that calling getpid() is the pid in task_struct

We can get the pid of the thread using gettid();

Advantages and disadvantages of multithreading and processes

advantage

1. Multithreading can realize concurrent execution of processes.
Assuming that there is only one execution flow in a process, it can only execute code serially. It will hang when it needs I/O waiting.
If there are multiple threads, one execution flow can be realized. The stream waits, while another execution stream executes other code. Improve the efficiency of the program, and it can better reflect its advantages
on multi-processor systems\

2. Thread switching is less expensive than process switching

A process has a complete page table address mapping space, and context
process switching is divided into two steps
: 1. Switch the page directory to use the new address space
2. Switch the kernel stack and hardware context.

As mentioned earlier, threads share the memory space of the process, so the first step thread is not executed, obviously the cost of switching threads is less

Another point is that when the process loads into the memory, it does not load the memory all at once, but establishes a mapping between it and the virtual address. If a page fault interrupt is triggered when writing to the virtual address, the corresponding file is loaded. into physical memory.
Therefore, switching to a new process will continue to trigger page fault interrupts at the beginning of running, and the efficiency is very low

Disadvantages of threads

1 Threads are unsafe
Because threads can access shared resources at the same time, there will be data inconsistencies caused by accessing critical resources
2. Threads run inside processes
1. If a thread crashes, the operating system will kill Dead process (reclaiming your resources), then all threads hang up
2. A thread calls a system call, all threads will be affected, such as fork(), there will be a bunch of threads running in the child process,
3. Or When a thread calls exit(), the process exits
3, which is difficult to write. The multi-thread execution order is not serial, and there will be more problems to consider. It is possible that the program runs correctly this time, and the next time It may go wrong.
This kind of occasional bug is the most difficult to debug. Of course, most of the time we write out the inevitable bug...

Creation and Waiting of POSIX Standard Threads under Linux

Because the thread library pthread under POSXI is not the default library of the system, you need to add -l (small L) to indicate the library name used when compiling

thread creation

   #include <pthread.h>

   int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                      void *(*start_routine) (void *), void *arg);

The first parameter is the thread ID number, which is an output parameter that needs to be declared in advance

The second is to create the property of appearing threads, because the bottom layer of pthread is also implemented through the system call clone(),

Creating a child process in clone can set its stack size, etc., but we don't care about its attributes in no special case,
so just fill in NULL

The third parameter is the function that needs to be executed after the thread is created. The last parameter parameter is the parameter of the execution function. If there are too many parameters, you can pass the
structure pointer

thread waiting

       #include <pthread.h>

       int pthread_join(pthread_t thread, void **retval);

       一个线程若果在结束后不进行等待退出
       其分配的资源不会被释放
       所以应该有一个线程等待该进程退出,

    也可使用

  #include <pthread.h>

 int pthread_detach(pthread_t thread); 分离线程,这样当线程退出后会自动回收自己的资源,

有一点应该注意,一个进程在任何时间点只能是join或者detach中的一个状态





test code

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
int retval = 0;
void* pthread_fun1(void* arg)
{
    pthread_t* thread_id = (pthread_t* )arg;
    int cnt = 3;
    while(cnt --)
    {
        printf("thread 1 : %0x cnt %d\n ",thread_id, cnt);
        sleep(1);

    }
    retval = 1;
    return (void*) &retval;
}
void* pthread_fun2(void* arg)
{
    //分离进程2
    pthread_detach(pthread_self());

    pthread_t* thread_id = (pthread_t* )arg;
    int cnt  = 3;
    while(cnt --)
    {
        printf("thread2 : %0x cnt:%d \n",thread_id, cnt);
        sleep(1);
    }
    return (void*) &retval;
}

int main()
{
    pthread_t main_thread, thread1,thread2;
    pthread_create(&thread1,NULL,pthread_fun1,(void *) &thread1);

    pthread_create(&thread2,NULL,pthread_fun2,(void *) &thread2);
    main_thread = pthread_self();
    while(1)
    {
        void  *ret;
        int ret1 = pthread_join(thread1,&ret);
        //阻塞式等待
        int ret2 = pthread_join(thread2,NULL);
        printf("main thread  %0x wait thread1 %0x wait 1 status : %d wait thread2 %0x wait 2 status :%d\n",
                main_thread,thread1, ret1,thread2,ret2);
        printf("%d\n",*(int* )ret);
        sleep(1);
    }























Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324694351&siteId=291194637