In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple
native threads from executing Python bytecodes at once. This lock is necessary mainly
because CPython’s memory management is not thread-safe. (However, since the GIL
exists, other features have grown to depend on the guarantees that it enforces.)
结论: 在CPython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势
from threading import Thread, Lock
import time
def work():
global n
with lock:
temp = n
time.sleep(0.1)
n = temp - 1
if __name__ == '__main__':
lock = Lock()
n = 100
li = []
for i in range(100):
t = Thread(target=work)
li.append(t)
t.start()
for t in li:
t.join()
print(n) # 结果肯定为0,由原来的并发执行变成串行,牺牲了执行效率保证了数据安全,不加锁则结果可能为99
from multiprocessing import Process
from threading import Thread
import time
import os
def work():
res = 0
for i in range(100000000):
res *= i
if __name__ == '__main__':
li = []
print(os.cpu_count()) # 4核
start = time.time()
for i in range(4):
p = Process(target=work) # 耗时 4.45s
p = Thread(target=work) # 耗时 16.35s
li.append(p)
p.start()
for p in li:
p.join()
stop = time.time()
print('run time is %s' % (stop - start))
如果并发的多个任务是I/O密集型:多线程效率高
from multiprocessing import Process
from threading import Thread
import time
import os
def work():
time.sleep(2)
print('==>')
if __name__ == '__main__':
li = []
print(os.cpu_count()) # 4核
start = time.time()
for i in range(400):
p = Process(target=work) # 耗时 13.34s, 大部分时间耗费在创建进程上
p = Thread(target=work) # 耗时 2.04s
li.append(p)
p.start()
for p in li:
p.join()
stop = time.time()
print('run time is %s' % (stop - start))