In the early operating system, the execution of each task was completely serial, and only after the completion of one task, another task would be executed, which we call
多道程序concept of concurrency introduced by modern operating systems :
Multi-program: When a program does not need to use the CPU for the time being, the system will suspend or interrupt the program. At this time, other programs can use the CPU. Multiple tasks achieve macro-concurrency under the control of the operating system. UndefinedMulti-programs improve the utilization of computer resources, but also cause multiple tasks to grab system resources, which is extremely inconvenient in development.
Serial and concurrency are concepts of the same dimension, the difference is:
Parallel and concurrency are not concepts in the same dimension:
The difference between concurrency and parallelism is whether it is executed at the same time. For example, when eating, the call comes, you need to stop eating to answer the call, and continue eating after receiving the call. This is a concurrent execution, but the call comes during the meal, and the answer is parallel while eating. .
Process: It is the running instance of the binary executable file in the computer memory. It can be simply understood as: an .exe file is a class, and the process is a new instance of the class. A process is the smallest unit of operating system resource allocation (such as virtual memory resources), and all codes are executed in the process.
In Unix systems, after the operating system is started, a process init with a process number (PID) of 1 will be run, which is the parent process of all other processes. The operating system can create multiple child processes through the fork() function, which can improve the utilization of computer resources.
After the process is created, it will have its own independent address space. The operating system will provide a data structure PCB to describe the process (Process Control Block). The PCB stores process management and control information and other data.
Because processes have independent address spaces, they cannot communicate directly between processes, and must use InterProcess Communication (IPC, InterProcess Communication) to achieve communication.
The operating system's memory will be divided into two major areas:
It is not difficult to find that the library function is actually encapsulated again on the basis of the system call function, which is convenient for developers to use. Of course, developers can use library functions to manipulate files, or directly use underlying system call functions (but this requires a lot of error handling).
When the program is running, the CPU has two states:
The reason why the operating system is designed in this way is out of memory safety considerations, the kernel address can only be used by the kernel's own function (system call function)!
Thread: a lightweight process opened by the operating system based on the process, which is the smallest unit of the operating system's scheduling and execution (that is, the object to which the cpu allocates time rounds)
Multiple threads can be created within a process. They have independent PCBs like the process, but there is no independent address space, that is, the address space is shared between threads. This also allows threads to communicate directly without IPC! ! (Because they are in the same address space).
Although threads bring the convenience of communication, if multiple threads in the same space modify the same data at the same time, it will cause resource competition, which is the most complicated problem in computer programming!
Processes and threads are at the operating system level, and coroutines are not a dimensional concept with them, so books like "Modern Operating Systems" do not propose the concept of coroutines.
Tips: Do not understand coroutines as lightweight threads!
Coroutine: When the program is being executed, the function can be interrupted, and then return to the execution at an appropriate time, that is, the coroutine runs in user mode
The advantage of the coroutine lies in its light weight and high execution efficiency:
Threads need to constantly switch contexts, and the coroutine will not actively hand over the right to use, unless the code actively requires switching, or I/O occurs, at this time it will switch to other coroutines, which can better solve the concurrency problem.
Thread synchronization: When a thread issues a function call, if the result is not obtained, the call does not return. At this time, other threads cannot call this function (because data consistency must be ensured).
Thread synchronization is to avoid causing data confusion. In fact, when multiple control flows work together to operate a shared resource, synchronization is required. For example, a synchronization mechanism is required among processes, threads, and signals. A common thread synchronization technique is a mutual exclusion lock.
The role of synchronization is to avoid conflicts that may occur when concurrently accessing shared resources.
Concept of synchronization:
In addition to using the synchronization method to realize the interaction of concurrent program data, you can also use the data transfer method (also known as communication).
In this way, the data can be sent to the data receiver without delay. Even if the data receiver is not ready to receive the data, it will not cause the data sender to wait. The data will be temporarily stored in a data structure called the communication buffer. The communication buffer is a special data structure that can be used by multiple programs at the same time, and the data receiver can receive them in the order in which the data is stored in the communication buffer after it is ready.
The current popular concurrency concept is: asynchronous non-blocking I/O, coroutine.