Playing with the history of python(2) multithreading 2

The concept of threads was proposed long before the emergence of multi-core CPUs. Multi-threading in the single-core era is mainly to keep the CPU from being in an idle state as much as possible, so that its computing power can always be utilized. But essentially, only one thread is executing at any one time.

Although only one thread is executing at any time, there are still some issues to be resolved, the most important of which is thread safety. The source of this problem is very simple. As I said before, the CPU executes the instructions one by one, but it should be noted that a line of code in a high-level language may be composed of multiple assembly instructions at the assembly language level. To give a simple example, perform an auto-increment operation on a variable in C language:

int a = 0;
int add(){
    a += 1;
    return a;
}

However, it is not so simple to become an assembly instruction. The two instructions that implement auto-increment are mainly these two instructions (most instructions are omitted):

    movl    a(%rip), %eax
    addl    $1, %eax

The reason why global variables are used in the example here is that thread safety and data synchronization are mainly for shared resources such as global variables. The above a(%rip) represents the value of the global variable a, and %eax is a register. The first instruction means to save the value of a in the eax register, and the second instruction adds 1 to the value in eax.
Let's consider a situation: now there are two threads A and B, both of which must call the add() function, then the expected value of a should be 2. If a context switch occurs after thread A executes the first instruction, the value of the eax register is the initial value of a, 0, and the CPU executes thread B. After thread B finishes executing, it returns 1 to a(%rip) , and then resume the execution of thread A. Since thread A will not execute the first instruction, the value of the eax register will not be updated, and it is still 0. After thread A is executed, it returns 1 to a(%rip). Ultimately, the value of a(%rip) is 1 instead of 2.
The above situation is what we often say is that the data is out of synchronization, or the thread is not safe. In this regard, people have proposed many methods, such as atomic operations, mutex locks, etc., the starting points are mainly the following two:
1. Ensure that the operation is not interrupted by the thread scheduling mechanism, either complete or not at all;
2. Even if The operation is interrupted by the thread scheduling mechanism, and other threads cannot obtain the right to use the related resources.

Now back to the language of python. In order to pass the time, the Dutch Guido van Rossum invented the scripting language python in 1989. Similar to java, python source code is first compiled into bytecode (pyc files in python projects), which are then interpreted by the interpreter. Similar to a layer of intermediate language between high-level language and assembly language.
write picture description here
In the above figure, a python expression can be composed of multiple interpreter instructions, and an interpreter instruction can be divided into multiple assembly instructions, which means that an interpreter instruction may be interrupted during execution, and the fact is As such, python's interpreter, CPython, is not thread-safe. Therefore, in order to ensure thread safety, the first thing to do is to allow an interpreter instruction to be executed without being affected by thread scheduling. The developers of the python interpreter have fiddled with the python global interpreter lock, or GIL for short. The GIL only allows one thread to run at any time. When the execution time of a thread reaches the threshold, the GIL is released, which makes thread scheduling much simpler.
So does the GIL solve the problem of thread safety? no. This is a deep pit in python. In the next blog, I will write some of my experiences while learning GIL.

Guess you like

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