• Index

### 关于作者

#### 多线程

Python的标准库提供了两个模块：`_thread``threading``_thread`是低级模块，`threading`是高级模块，对`_thread`进行了封装。绝大多数情况下，我们只需要使用`threading`这个高级模块。

``````import time, threading

# 新线程执行的代码:
def loop():
n = 0
while n < 5:
n = n + 1
time.sleep(1)

t.start()
t.join()
``````

``````thread MainThread is running...
``````

### Lock

``````import time, threading

# 假定这是你的银行存款:
balance = 0

def change_it(n):
# 先存后取，结果应该为0:
global balance
balance = balance + n
balance = balance - n

for i in range(100000):
change_it(n)

t1.start()
t2.start()
t1.join()
t2.join()
print(balance)
``````

``````balance = balance + n
``````

1. 计算`balance + n`，存入临时变量中；
2. 将临时变量的值赋给`balance`

``````x = balance + n
balance = x
``````

``````初始值 balance = 0

t1: x1 = balance + 5 # x1 = 0 + 5 = 5
t1: balance = x1     # balance = 5
t1: x1 = balance - 5 # x1 = 5 - 5 = 0
t1: balance = x1     # balance = 0

t2: x2 = balance + 8 # x2 = 0 + 8 = 8
t2: balance = x2     # balance = 8
t2: x2 = balance - 8 # x2 = 8 - 8 = 0
t2: balance = x2     # balance = 0

``````

``````初始值 balance = 0

t1: x1 = balance + 5  # x1 = 0 + 5 = 5

t2: x2 = balance + 8  # x2 = 0 + 8 = 8
t2: balance = x2      # balance = 8

t1: balance = x1      # balance = 5
t1: x1 = balance - 5  # x1 = 5 - 5 = 0
t1: balance = x1      # balance = 0

t2: x2 = balance - 8  # x2 = 0 - 8 = -8
t2: balance = x2   # balance = -8

``````

``````balance = 0

for i in range(100000):
# 先要获取锁:
lock.acquire()
try:
# 放心地改吧:
change_it(n)
finally:
# 改完了一定要释放锁:
lock.release()
``````

### 多核CPU

``````import threading, multiprocessing

def loop():
x = 0
while True:
x = x ^ 1

for i in range(multiprocessing.cpu_count()):
t.start()
``````

GIL是Python解释器设计的历史遗留问题，通常我们用的解释器是官方实现的CPython，要真正利用多核，除非重写一个不带GIL的解释器。

### 小结

Python解释器由于设计时有GIL全局锁，导致了多线程无法利用多核。多线程的并发在Python中就是一个美丽的梦。