CPython and threading module Lock()

Since CPython has the GIL, no threads are allowed to execute python code at the same time, thus there seems to be thread safety within a given process.

What is the purpose then of the python threading module Lock () ? What synchronization problems can still occur in CPython that the Lock () helps with even though no threads can execute at the same time ?


The GIL only makes sure that only one thread can run at a time. It is still possible that a thread gets interrupted between instructions and another thread has a chance to run. Therefore if two threads access a shared resource the access needs to be protected with a lock.

Let's take this example:

from threading import Thread

i = 0

def func():
    global i
    while i < 1000000:
        i += 1
        if i != i:
            print("i was modified")

for _ in range(10):
    Thread(target=func).start()

Although it looks like the if condition can't possibly ever be true, there is a good chance that you'll see the line printed. How can that be?

If you look at the disassembled bytecode of func (by calling dis.dis(func) from the dis module), this is what you'll get:

  7           0 SETUP_LOOP              51 (to 54)
        >>    3 LOAD_GLOBAL              0 (i)
              6 LOAD_CONST               1 (1000000)
              9 COMPARE_OP               0 (<)
             12 POP_JUMP_IF_FALSE       53

  8          15 LOAD_GLOBAL              0 (i)
             18 LOAD_CONST               2 (1)
             21 INPLACE_ADD
             22 STORE_GLOBAL             0 (i)

  9          25 LOAD_GLOBAL              0 (i)
             28 LOAD_GLOBAL              0 (i)
             31 COMPARE_OP               3 (!=)
             34 POP_JUMP_IF_FALSE        3

 10          37 LOAD_GLOBAL              1 (print)
             40 LOAD_CONST               3 ('i was modified')
             43 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             46 POP_TOP
             47 JUMP_ABSOLUTE            3
             50 JUMP_ABSOLUTE            3
        >>   53 POP_BLOCK
        >>   54 LOAD_CONST               0 (None)
             57 RETURN_VALUE

The relevant instructions are 25 and 28. If the thread gets interrupted between those two instructions, another therad can modify the global variable i and the stored values will be different.

链接地址: http://www.djcxy.com/p/86490.html

上一篇: Malloc内存问题

下一篇: CPython和线程模块Lock()