11月2日GIL机制、计算密集型和io密集型

发布时间 2023-11-02 20:05:40作者: songjunwan

CPython

CPython是Python的一种实现,它是官方解释器之一,而Python是编程语言本身的名称。然后CPython里面就有一个机制GIL(全局解释器锁),它是CPython中的一个重要特性,它对多线程程序的执行方式产生了影响。

GIL机制

什么是GIL机制?

1.在python解释器中有一把GIL锁,它的本质是一把互斥锁。

因为GIL锁的存在同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势

2.GIL可以比喻成执行权限,同一进程下的所有线程要想执行都需要抢这个权限

3.GIL是CPython中的一个机制叫做全局解释器锁。

Jython、IronPython 和 PyPy(了解)

  1. Jython:
    • Jython 是 Python 在 Java 平台上的实现。
    • 它将 Python 代码编译成 Java 字节码,从而可以与 Java 代码集成,并直接使用 Java 生态系统的各种库和工具。
    • Jython 具有与 CPython 不同的特性和行为,因为它在 Java 虚拟机上运行,不受 GIL 的限制。
  2. IronPython:
    • IronPython 是 Python 在 .NET 平台上的实现。
    • 它可以与 .NET 语言(如 C#)相互调用,并利用 .NET 生态系统的各种库和工具。
    • 类似于 Jython,IronPython 不受 GIL 的限制。
  3. PyPy:
    • PyPy 是一种 Python 解释器,其目标是提供更高的性能。
    • PyPy 使用即时编译技术,可以加速 Python 代码的执行速度,相对于 CPython,它通常更快。
    • 尽管 PyPy 仍然具有 GIL,但由于其性能改进,它在某些情况下可以更好地处理多线程并发。

同时这三个不受GIL机制的影响

为什么要有GIL机制

在并发编程里面垃圾回收机制需要有GIL机制来保证安全

这个GIL了解就行了,就当扩展看看。

例子

我现在有四个任务需要处理,处理方式肯定是要玩出并发的效果,解决方案:

方案一:开启四个进程

方案二:一个进程下,开启四个线程

下面给出具体类型:

计算密集型

每个都要计算10s

多线程:

在同一时刻只有一个线程会被执行,也就意味这每个10s都不能省,分开每个都要计算10s,共40s

测试代码如下:

import time
from threading import Thread


# 计算密集型(多线程)
def work1():
    res = 0
    for i in range(100000000):
        res += 1


if __name__ == '__main__':
    t_list = []
    start = time.time()  # 这里输出开始的时间
    for i in range(4):
        t = Thread(target=work1)
        t_list.append(t)
        t.start()
    for t in t_list:
        t.join()
    end = time.time()

    print('多线程', end - start)  # 多线程运行这个跑了14.351047039031982秒

多进程:

可以并行的执行多个线程,10s+开启进程的时间

测试代码入如下:

import time
from multiprocessing import Process


# 计算密集型(多进程)
def work1():
    res = 0
    for i in range(100000000):
        res += 1


if __name__ == '__main__':
    t_list = []
    start = time.time()  # 这里输出开始的时间
    for i in range(4):
        t = Process(target=work1)
        t_list.append(t)
        t.start()
    for t in t_list:
        t.join()
    end = time.time()

    print('多进程', end - start)  # 多进程运行此代码用了4.870921611785889秒

这两个代码的比拼结果如下

通过结果说明了这个集型适合用多进程

io(输入/输出)密集型

4个任务每个任务90%大部分时间都在io

每个任务io10s

多线程:

可以实现并发,每个线程io的时间不咋占用CPU,10s + 4个任务的计算时间

测试代码如下:

# io密集型(多线程)
import time
from threading import Thread


def work1():
    x = 1 + 1
    time.sleep(5)


if __name__ == '__main__':
    t_list = []
    start = time.time()  # 这里输出开始的时间
    for i in range(4):
        t = Thread(target=work1)
        t_list.append(t)
        t.start()
    for t in t_list:
        t.join()
    end = time.time()

    print('多线程', end - start)

多进程:

可以实现并行,10s + 1个任务执行的时间+开启进程的时间

测试代码如下:

# io密集型(多线程)
import time
from threading import Thread


def work1():
    x = 1 + 1
    time.sleep(5)


if __name__ == '__main__':
    t_list = []
    start = time.time()  # 这里输出开始的时间
    for i in range(4):
        t = Thread(target=work1)
        t_list.append(t)
        t.start()
    for t in t_list:
        t.join()
    end = time.time()

    print('多线程', end - start)

两者结果对比图

虽然就这一点点的时间差距问题,io密集型还是适合多线程