GIL全局解释器锁及协程

GIL全局解释器锁

1、什么是GIL全局解释器锁

GIL本质是一把互斥锁,相当于执行权限,每个进程内都会存在一把GIL同一进程内的多线程,必须抢到GIL之后才能使用Cpython解释器来执行自己的代码,即同一进程下的多个线程无法实现并行,但可以实现并发

Cpython解释器下想实现并行可以开启多个进程

2、为何要有GIL

因为Cpython解释器的垃圾回收机制不是线程安全的,保证了数据的安全

3、GIL全局解释器的优缺点

优点:保证了数据安全

缺点:单个进程下开启多个线程只能实现并发不能实现并行

4、选择多进程还是多线程?

单核或多核I/O密集型下使用:多线程

单核计算密集型下使用:多线程

多核计算密集型下使用:多进程

多cpu,意味着可以有多个核并行完成计算,所以多核提升的是计算性能

每个cpu一旦遇到I/O阻塞,仍然需要等待,所以多核对I/O操作没什么用处

对于一个程序来说不可能是纯IO型或者纯计算型,我们只能相对的判断是IO密集型还是计算密集型,来选择多进程还是多线程

单核情况下:

? 开启四个任务是计算密集型的,没有多核来并行计算,开多个进程,只是徒增进程的开销内存资源,应该使用多线程

? 开启四个任务是IO密集型的,开启多进程也是徒增,来回切换的速度还不如开启多线程的,所以应该使用多线程

多核情况下:

? 开启四个任务是计算密集型的,多核意味着多个CPU去计算,开启多进程可以同一时刻去计算,所以应该使用多进程

? 开启四个任务是IO密集型的,再多的核也在在等待,来回切换的速度进程不如线程的,所以应该使用多线程

5、多线程多进程多核下性能测试

from multiprocessing import Process
from threading import Thread
import os
import time

# 计算密集型
def task1():
    i = 0
    for line in range(110000000):
        i += 1

if __name__ == '__main__':
    print(os.cpu_count())  # 查看计算机几核的
    list1 = []
    start_time = time.time()
    for i in range(4):
        p1 = Process(target=task1)  # 4进程下: 17.369488954544067
        # t1 = Thread(target=task1) # 4线程下: 27.991361618041992
        p1.start()
        # t1.start()
        # list1.append(t1)
        list1.append(p1)
    for i in list1:
        i.join()
    end_time = time.time()
    print(end_time - start_time)

# IO密集型
def task2():
    time.sleep(1)

if __name__ == '__main__':
    print(os.cpu_count())
    start_time = time.time()
    list2 = []
    for i in range(40):
        # p2 = Process(target=task2) #40进程下: 11.374541282653809
        t2 = Thread(target=task2)  # 40线程下: 1.010239839553833
        # p2.start()
        t2.start()
        # list2.append(p2)
        list2.append(t2)
    for i in list2:
        i.join()
    end_time = time.time()
    print(end_time - start_time)

协程

1、什么是协程

进程:资源单位

线程:执行单位

协程:单线程下实现并发

在I/O密集型的情况下,使用协程提高执行效率

手动的实现在同一线程下 “ 遇到I/O切换+保存状态 ” 让操作系统误以为没有I/O操作,将CPU执行权限继续交给你

即:在单线程下实现多个任务遇到IO就切换可以降低单线程的IO时间,从而最大限度的提升单线程的效率

2、实现协程

gevent模块:遇到I/O自动切换并保存状态

使用gevent模块中的monkey,monkey.patch_all()来监视是否遇到IO操作,再使用spawn来创建协程,使用joinall替代join,使协程运行完再结束线程,joinall中放入得到的对象到列表中

from gevent import spawn
from gevent import joinall
from gevent import monkey
import time

# 补丁:监听所有的任务是否有IO操作
monkey.patch_all()

def task1(name):
    print(f'{name}开始')
    time.sleep(1)
    print(f'{name}结束')

def task2():
    print('task2开始')
    time.sleep(3)
    print('task2结束')

def task3():
    print('task3开始')
    time.sleep(5)
    print('task3结束')

if __name__ == '__main__':
    start_time = time.time()
    # 创建协程
    sp1 = spawn(task1,'task1')
    sp2 = spawn(task2)
    sp3 = spawn(task3)
    # sp1.join()
    # sp2.join()
    # sp3.join()
    joinall([sp1, sp2, sp3]) # 相当于 sp.join(),注意放入列表中
    end_time = time.time()
    print(end_time - start_time)
    # task1开始
    # task2开始
    # task3开始
    # task1结束
    # task2结束
    # task3结束
    # 5.013161897659302

原文地址:https://www.cnblogs.com/Mr-shen/p/12019350.html

时间: 2024-09-30 14:54:58

GIL全局解释器锁及协程的相关文章

进程、线程与GIL全局解释器锁详解

进程与线程的关系: 1. 线程是最小的调度单位 2. 进程是最小的管理单元 3. 一个进程必须至少一个线程 4. 没有线程,进程也就不复存在 线程特点: 3 线程的并发是利用cpu上下文的切换(是并发,不是并行) 4 多线程执行的顺序是无序的 5 多线程共享全局变量 6 线程是继承在进程里的,没有进程就没有线程 7 GIL全局解释器锁 8 只要在进行耗时的IO操作的时候,能释放GIL,所以只要在IO密集型的代码里,用多线程就 9 很合适 线程详解: import threading # --->

python 并发编程 多线程 GIL全局解释器锁基本概念

首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念. 就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码. >有名的编译器例如GCC,INTEL C++,Visual C++等.Python也一样,同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行环境来执行. 像其中的JPython就没有GIL.然而因为CPython是大部分环境下默认的Python执行环境.所以在很多人的概

GIL(全局解释器锁)

GIL(全局解释器锁) 我们知道多进程(mutilprocess) 和 多线程(threading)的目的是用来被多颗CPU进行访问, 提高程序的执行效率. 但是在python内部存在一种机制(GIL),在多线程 时同一时刻只允许一个线程来访问CPU. GIL 并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念.就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码.有名的编译器例如GCC,INTEL C++,Visual C++等.

Python之路-python(paramiko,进程和线程的区别,GIL全局解释器锁,线程,进程)

一.paramiko 二.进程.与线程区别 三.python GIL全局解释器锁 四.线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者消费者模型 Queue队列 一.paramiko 用于远程连接并执行简单的命令 使用用户名密码连接: 1 import paramiko 2 3 # 创建SSH对象 4 ssh = paramiko.SSHClient() 5 # 允许连接不在know_hosts文件中的主机 6 ssh.set

GIL全局解释器锁和进程池.线程池

GIL全局解释器锁 GIL本质就是一把互斥锁,是夹在解释器身上的,同一个进程内的所有线程都需要先抢到GIl锁,才能执行解释器代码 GIL的优缺点: 优点:保证Cpython解释器内存管理的线程安全 缺点:同一个进程内所有的线程同一时刻只能有一个执行,也就是说Cpython解释器的多线程无法实现并行,无法取得多核优势 GIL与单线程 每个进程的内存空间中都有一份python解释器的代码,所以在单线程的情况下,GIL锁没有线程争抢,只有垃圾回收机制线程会定时获取GIL权限 GIL与多线程 有了GIL

GIL全局解释器锁

1.什么是GIL全局解释器锁? GIL并不是Python的特性,而是CPython解释器的概念.Python完全可以不依赖于GIL. GIL本质是一把互斥锁,是加在CPython解释器身上的,同一个进程内的所有线程都需要先抢到GIL锁,才能执行解释器代码 2.为什么会有GIL? 为了利用多核,Python开始支持多线程,而解决多线程之间数据完整性和状态同步的最简单方法自然就是加锁,于是有了GIL这把超级大锁. 简单的说GIL的存在更多的是历史原因. 3.GIL的影响 GIL的存在会对多线程的效率

Python 36 GIL全局解释器锁

一:GIL全局解释器锁介绍 在CPython中,全局解释器锁(或GIL)是一个互斥锁, 它阻止多个本机线程同时执行Python字节码.译文:之所以需要这个锁, 主要是因为CPython的内存管理不是线程安全的.(然而,由于GIL的存在, 其他特性已经变得依赖于它所执行的保证.) 1. 什么是GIL全局解释器锁GIL本质就是一把互斥锁,相当于执行权限,每个进程内都会存在一把GIL,同一进程内的多个线程必须抢到GIL之后才能使用Cpython解释器来执行自己的代码,即同一进程下的多个线程无法实现并行

10 并发编程-(线程)-GIL全局解释器锁&死锁与递归锁

一.GIL全局解释器锁 1.引子 在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势 首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念. 就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码.>有名的编译器例如GCC,INTEL C++,Visual C++等.Python也一样,同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行

python第三十七天,GIL全局解释器锁*****,线程池与进程池 同步异步,阻塞与非阻塞,异步回调

GIL全局解释器锁 1.什么是GIL 官方解释:'''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