Python GIL 全局解释器锁

Python GIL 全局解释器锁

  • 1、`GIL`
  • 2、`CPU`密集型

1、GIL

CPython在解释器进程级别有一把锁,叫做GIL(Global Interpreter Lock),即全局解释器锁。

GIL保证CPython进程中,只有一个线程执行字节码。甚至是在多核CPU的情况下,也只允许同时只有一个CPU上运行该进程的一个线程。

CPython中:

  • IO密集型,某个线程阻塞,就会调度其他就绪线程
  • CPU密集型,当前线程可能会连续的获得GIL,导致其它线程几乎无法使用CPU

CPython中由于有GIL的存在,IO密集型,使用多线程较为合理;CPU密集型,使用多进程,要绕开GIL

新版Python正在努力优化GIL的问题,但不是移除。移除GIL,会将此CPython单线程的执行效率。

Python中绝大多数的内置数据结构的读写操作都是原子操作。由于GIL的操作,Python的内置数据类型在多线程编程时就变成安全的了,但是实际上他们本身并不是线程安全类型。

如果在意GIL,可使用erlang Go等语言。

2、CPU密集型

查看下面两个示例,一个主线程单独运算和四个线程分别运算,时间竟然相差无几,验证了GIL锁的存在。

CPU密集型的运算,适合使用多进程。

import logging
import datetime

FORMAT = "%(asctime)s %(threadName)10s %(thread)8d %(message)s"
logging.basicConfig(level=logging.INFO, format=FORMAT)

start = datetime.datetime.now()


def clac(n: int=1000000000):
    sum = 0
    for _ in range(n):
        sum += 1


for i in range(4):
    clac()


delta = (datetime.datetime.now() - start).total_seconds()
logging.info(delta)
# 2022-04-21 10:40:51,945 MainThread    50912 107.745666
import logging
import datetime
import threading

FORMAT = "%(asctime)s %(threadName)10s %(thread)8d %(message)s"
logging.basicConfig(level=logging.INFO, format=FORMAT)

start = datetime.datetime.now()


def clac(n: int=1000000000):
    sum = 0
    for _ in range(n):
        sum += 1
    logging.info(sum)
    return sum


for i in range(4):
    t = threading.Thread(target=clac, name='clac-{}'.format(i + 1))
    t.start()
    t.join()


delta = (datetime.datetime.now() - start).total_seconds()
logging.info(delta)
# 2022-04-21 10:44:42,513     clac-1    41712 1000000000
# 2022-04-21 10:45:09,500     clac-2    41900 1000000000
# 2022-04-21 10:45:36,390     clac-3    46436 1000000000
# 2022-04-21 10:46:02,827     clac-4      908 1000000000
# 2022-04-21 10:46:02,827 MainThread    10584 107.654591

你可能感兴趣的:(Python,python)