Multi-threaded programming and lock


  In multiple processes, each process independent of each other, does not affect the stability of the main program, the child process crash does not matter; by increasing the CPU, it can easily expand performance; can minimize the impact of thread lock / unlock, and greatly improve performance, even the low efficiency of the algorithm modules running thread does not matter; each child has a 2GB address space and related resources, to achieve the overall performance of the upper limit of very large, however, complex logic control, and the main program needs to interact; required across process boundaries, If there is a large amount of data transfer, not so good for a small amount of data transfer, compute-intensive multi-process scheduling overhead is relatively large; therefore, we can use the multi-threading.

First, the pros and cons of multi-threaded

advantage:

1) It is a very "frugal" multitasking operating mode. In the Linux system, start a new process must be assigned to its separate address space, the establishment of a large number of data tables to maintain its code segment, stack and data segments, this is an "expensive" multi-task work. While running on multiple threads within a process, using the same address space between each other, share most of the data, start a thread space it takes far less than it takes to start a process space, and, switching between threads to each other the time required is far less than the time required to switch between processes. Of course, on the specific system, this data may have a greater difference;
facilitate communication mechanism between 2) thread, since the thread between the process of sharing the same data space, the data of one thread may be used by other threads directly this is not only fast, but also convenient;
3) the multi-CPU system more efficient. When the operating system will ensure that the number of threads is not larger than the number of CPU, running different threads on different the CPU;
. 4) to improve the program structure. A long and complex process can be considered divided into multiple threads into several independent or semi-independent part of the run, such a program would be beneficial to understand and modify.

Disadvantages:

1) Each main thread common address space, address space is limited to 2GB;
2) and the synchronization between the thread lock control troublesome;
crash 3) a thread may affect the stability of the entire process;
4) after reaching a certain extent the number of threads, even then increase the CPU can not improve performance;
limited 5) threads can improve overall performance, and more than a thread after thread scheduling itself is a troublesome thing, you need to consume more CPU

Next, we come to understand the specific concepts and simple to use threads.

Second, shallow knowledge thread

1. threading model

As mentioned earlier, working with threads in the same process space, and the child thread and the main thread of shared resources, his model is such that

Here Insert Picture Description
main () function is called thread main thread, the main thread and can create multiple sub-thread, son there are different tasks between threads work, and what specific task, perform the task which parameters they need, winner of this thread when they passed in the creation;
threads can improve application processing, such as multi-core environment in a file I / O performance properties or socket I / O, etc. will produce the clogging. In Unix systems, a process that contains many things, including executable programs and a host of other resources such as file descriptors address space. In many cases, between different code to complete related tasks you need to exchange data. If the multi-process manner, the process of creating the time it takes bigger slice than the thread, another inter-process communication is too much trouble, the need for frequent switching in user space and kernel space, a large overhead. But if you use a multi-threaded approach, because you can use the shared global variable, so the communication between threads (data exchange) becomes very efficient.

2. Thread the properties and function

pthread_attr_t

Before creating the thread, we need to define a pthread_attr_t structure type,
the structure members are as follows:


typedef struct
{
        int detachstate; 线程的分离状态  
        int schedpolicy; 线程调度策略
        struct sched_param schedparam; 线程的调度参数
        int inheritsched; 线程的继承性
        int scope; 线程的作用域
        size_t guardsize; 线程栈末尾的警戒缓冲区大小
        int stackaddr_set;
        void * stackaddr; 线程栈的位置
        size_t stacksize; 线程栈的大小
}pthread_attr_t;

Thread attribute structure member reference blog: Multithreading property pthread_attr Comments

 As a member of the structure of the first listed, the detachstate need to add that (a function which will be referred to one analysis):

  After a process is created, it will first create a default thread, usually called this thread is the main thread (or threads of control), C / C ++ program, the main thread is through the main function into the thread, the main thread calls pthread_create ( ) thread creation is called the child thread, the child thread can have its own entrance function, which is specified by the user at the time of creation. Each thread has its own thread ID, you can obtain function by pthread_self (). The most common thread model, in addition to the main thread is special, other threads once created, is a peer relationship, implied hierarchical relationship does not exist between each other. The maximum number of threads per process can be created both in the windows or Posix, the default relationship between the main thread and the child thread is determined by the specific implementation decisions: whether or not the child thread is finished, once the main thread completes exit, all sub-thread execution will be terminated. Then the whole process ends or dead, to maintain a portion of the thread termination status execution but not yet destroyed, and the process must be destroyed after the destruction of all of its threads, then the process is in dead state. Thread function completes exit, terminate or otherwise very, terminate the thread into the state, but for the allocation of system resources thread
source is not necessarily release, possibly before the system is rebooted, has not been able to release, the thread termination state, still as a thread entity exists in the operating system, and when destroyed, depending on the thread attributes. In this case, the main thread and the child thread is usually defined the following two relationships:

  1. Can join (the Joinable) : In this relationship, the main thread needs to wait for a clear implementation of the operation, after the child thread, the main thread of execution wait operation is completed, the child thread and join the main thread, then wait for the main thread to continue operations after the next step. The main thread must meet the child thread can rendezvous. In the main thread wait thread function calls an internal function object to achieve sub-thread, even if the child thread can be finished before the main thread, into the termination state, also joined the operation must be performed, otherwise, the system will never take the initiative to destroy threads, assigned to the system resources thread will never release.
  1. Phase separation (detached) : represents the child thread and do not need to join the main thread, which is the phase separation, in this case, the child thread to terminate once into the state, this approach is more commonly used in the case of the number of threads, and sometimes let the main thread one by the end of the thread waits for the child, or make arrangements for each child thread the main thread to wait for the end of the sequence, it is difficult or impossible, so in a more complicated by sub-thread cases, this approach will often use. Separating a thread state of the thread determine in what way to terminate itself, in the case of default, the thread is non-isolated state, in this case, the original thread wait for the end of the thread is created only when pthread_join function returns, threads created considered terminated own release system resources occupied, and the thread is not separated from other threads waiting to run their own end, the thread will cease immediately release system resources.

  For these properties, we need to set a separate state of the thread, if necessary, also need to modify the stack size for each thread. After each thread is joinable to create a default state, this state needs the main thread to call it quits pthread_join wait, otherwise the child thread at the end, memory resources can not be released resulting in a memory leak. Therefore, the general thread will be provided as a separate state, there are two specific methods we create threads:

  1. Inside thread calls pthread_detach (pthread_self ()) This method is the easiest
  2. Set PTHREAD_CREATE_DETACHED property in the Properties settings to create a thread in
pthread_attr_init()
#include <pthread.h>

int pthread_attr_init(pthread_attr_t *attr);   //初始化线程对象的属性;
int pthread_attr_destroy(pthread_attr_t *attr);   //销毁一个目标结构,并且使它在重新初始化之前不能重新使用。

Only one parameter, that is the thread attribute structure defined, returns 0 on success, failure to return a nonzero error number;

pthread_attr_setstacksize()
#include <pthread.h>

int pthread_attr_setstacksize(pthread_attr_t *attr,size_t stacksize); 

The first parameter is a property of the thread structure, the second is the size of the thread stack; 0 returns success, failure to return a non-zero;

pthread_attr_setdetachstate()
#include <pthread.h>

int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

Set the thread is separate or join, take PTHREAD_CREATE_DETACHED when, after the implementation of the thread without having to wait for others, self-destruct, free up memory space;
take PTHREAD_CREATE_JOINABLE , the main thread should call pthread_join () function to wait for the child threads to exit, because we are against him interested in the state of exit, the main thread is blocked at the end of this sub-thread knows, the function returns, the thread is destroyed, freeing up space.
Returns 0 on success, failure to return a non-zero;

pthread_create();
#include <stdio.h>

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

The first argument is a pointer to the thread identifier used to return the thread ID;
The second parameter is used to set the thread attributes;
the third parameter is the starting address of the thread running the function, i.e., the task required by the function ;
the last parameter is a parameter to run the function.

Third, the lock

  If a resource is different threads access to modify, then we put this resource is called the critical resource , then the resource access to modify the relevant code is called the critical region . So how to solve shared the same shared resource among multiple threads, multi-threaded programming is an issue to be considered.

Suppose we are doing something which a thread A need to frequently used process in the value of a variable, but this time, the thread B also uses this value and change the value of the variable, the thread A in each the value of this critical resource when times get are not the same, will lead the work of thread a can not be executed properly!
At this point, we need to use the lock.

Blocking locks

Multiple threads call the same method at the same time, all threads are queued to deal with. Let the thread into the blocked state to wait, when to obtain the corresponding signal (wake-up time), before they can enter the ready thread ready, prepare all threads ready by competition, went into operation.

Non-blocking lock

Multiple threads at the same time call a method, when one of the first thread to acquire a lock, then other threads judge did not get the lock, then return directly, and only when the first thread releases the lock to get, other threads can in, other threads will get a failure before it is released.

Spin and mutex lock

When a thread to acquire the lock, if the lock has been acquired by other threads, then the thread will wait for the cycle, and then continue to determine whether the lock is successfully acquired, until the lock is acquired will exit the loop. Thread acquiring the lock has been active, as has been invoked while loop, but did not perform any tasks effectively, the use of this lock will cause busy-waiting.
Mutex also to protect shared resources of sync, at any time, at most one holder, it said, can only have at most one execution unit at any time to acquire a lock. But the two slightly different scheduling mechanisms. For the mutex, if the resource is already occupied, the resource request can only go to sleep. But the spin lock without causing the caller to sleep, if the spin lock has been held another execution unit, the caller has been to see whether the spin cycle lock holder has released the lock there.

Deadlock

If multiple threads to be called multiple objects, it may be a "deadlock" when locked. For example: A, B two threads simultaneously using the two shared variables m and n, and each has its own corresponding lock variable M and N. A time to get the first thread lock access M m, then he needs to get access to the lock variable n-N; case B if waiting for the lock thread holding N M, then the lock, causing the thread "deadlock."
Here Insert Picture Description

Four necessary conditions for Deadlock
1, mutually exclusive: a resource allows only one process to access, that is, once the resource is assigned to a process, other processes can no longer access until the process access node
beam.
2, possession and wait: a process itself takes the resource (one or more), as well as resources have not been met, is waiting for other processes to release the resource.
3, can not be seized: someone else has possession of a resource, you can not because they need the resources to go to other people's resources take it over.
4, circular wait: there is a process chain, so that each process has played at least one of the resources needed for the next process.
When the above four conditions are met, will definitely lead to a deadlock, the process deadlock can not go on, they can not release the resources held. This will cause the CPU throughput. So a deadlock situation is a waste of system resources and affect the performance of the computer. So, to solve the deadlock problem is quite necessary up.
Deadlock requires four conditions, then, as long as there is at least one condition of the four conditions are not met, it is impossible deadlock occurred. Since the condition is non-exclusive shared resources necessary, not only can not be changed, it should also be guaranteed, so the other three main conditions for deadlock damage.

a, destroy the "possession and wait" Condition
1: All process before starting to run, you must apply once all the resources in its entire run in need.
Advantages: easy to implement and secure. Cons: Because a resource is not satisfied, the process can not be started, while others have been met will not be utilized resources, severely reducing the utilization of resources, resulting in
waste of resources. The process hunger frequently.
Method 2: This method is the first method of improvement, the process is only allowed access to resources needed for the operation early, they start to run, during operation gradually freed resource allocation had been used up to then go to new request resources. In this case, resource utilization will be improved, also the problem of hunger reduction process.
b, destruction "can not be seized" condition
when a process already holds some resources in the proposed new resource request is not met, it must release all resources have been held, to be used later when needed and then re-apply. This means that the process has possession of resources will be briefly released or be seized. This method is more complex to implement, and the cost is relatively large. Release resources have been held before is likely to lead to effective work processes, etc., repeated application and release of resources will lead to the implementation process is hugely delayed, it will not only prolong the process of turnaround, but also affect the system throughput.
C, destruction "waiting loop" conditions
can be prevented by the linear sequence defined resource types, each resource may be numbered, when a process occupies a resource number i, then the next time that application resources are only
able to apply a number greater than i resources.

Released eight original articles · won praise 11 · views 302

Guess you like

Origin blog.csdn.net/weixin_45121946/article/details/104605316