全局解释器和线程

Posted bs2019

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了全局解释器和线程相关的知识,希望对你有一定的参考价值。

1.全局解释器锁

1.1python解释器:

? -Cpython c语言

? -Jpython java

1.2GIL :全局解释器

? -翻译:在同一个进程下开启的多线程,同一时刻只能有有一个线程执行,因为cpython的内存管理不是线程安全。

? -GIL全局解释器,本质上是一把互斥锁,保证数据安全

? 在Cpython解释器中,同一个进程下开启多个线程,同一时刻只能有一个线程执行,无法利用多核优势。

? -为什么要有全局解释器锁:

? -没有锁

? -GIL全局解释器锁的优点:

? -优点:

? 保证数据的安全

? -缺点:

? 单个进程下,开启多个线程,牺牲执行效率了,无法实现并行,只能实现并发。

? -IO密集型: 多线程

? -计算机密集型:多进程

import time
from threading import Thread
n = 100
def task():
    global n
    m = n
    time.sleep(3)
    n =m -1####实际产生了10个99  最后一个只打印了一个n
    
    #print(n)

if __name__ == '__main__':
    list = []
    for line in range(10):
        t = Thread(target = task)
        t.start()
        list.append(t)

    for t in list:
        t.join()
    print(n)
    >>>>>>>>>>>>>>>>>>>>>>
    99

2.协程

-定义:

? -进程:资源单位

? -线程:执行单位

? -协程:单线程西实现并发

? -在IO密集的情况下,使用协程能提高最高效率

注意:协程不是任何单位,使用协程能提高最高效率

协程的目的:

? -手动实现“遇到IO切换+保存状态” ,因为是在单线程下,控制单线程的多个任务在一个任务遇到io,就切换到另外一个任务执行,这样保证了,线程能够最大限度的处于就绪化,即随时都可以被cpu执行的状态,可以去欺骗操作系统,让操作系统误以为没有io操作,从而将cpu的执行权限交给你。

? -必须只有单线程实现并发,

? -协程指的是单个线程,一旦线程出现阻塞,及那个会阻塞整个线程

from gevent import monkey  # 猴子补丁   
monkey.patch_all()  # 监听所有的任务是否有IO操作 
#上面的2个必须写在文件的开头,在time socket的模块之前,这样形成的io 可以直接识别
from gevent import spawn  # spawn(任务)  spawn(函数名,参数,参数)
from gevent import joinall
import time

def task1():
    print('start from task1...')
    time.sleep(1)
    print('end from task1...')

def task2():
    print('start from task2...')
    time.sleep(3)
    print('end from task2...')

def task3():
    print('start from task3...')
    time.sleep(5)
    print('end from task3...')


if __name__ == '__main__':

    start_time = time.time()
    sp1 = spawn(task1)
    sp2 = spawn(task2)
    sp3 = spawn(task3)
    # sp1.start()
    # sp2.start()
    # sp3.start()
    # sp1.join()
    # sp2.join()
    # sp3.join()
    joinall([sp1, sp2, sp3])

    end_time = time.time()

    print(f'消耗时间: {end_time - start_time}')
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start task1...
start task2...
start task3...
end task1...
end task2...
end task3...
消耗时间:3.0044186115264893

3.使用多线程提高效率

from threading import Thread
from multiprocessing import Process
import time

#计算密集型任务
def task1():
    i = 10
    for line in range(1000000):
        i += 1

#io密集型任务
def task2():
    time.sleep(3)

if __name__ == '__main__':
    #测试多进程
    #计算密集型
    a = time.time()
    list1 = []
    for line in range(6):
        p = Process(target = task1)
        print(p)
        p.start()
        list1.append(p)

    for p in list1:
        p.join()
    b = time.time()
    print(f'计算进程密集型消耗的时间:{b-a}')

    #测试IO密集型
    a = time.time()
    list2 = []
    for line in range(6):
        p = Process(target = task2)
        p.start()
        list2.append(p)

    for p in list2:
        p.join()
    b = time.time()
    print(f'IO进程密集型消耗时间:{b-a}')

    #2.测试多线程的
    #测试计算密集型
    a = time.time()
    list1 = []
    for line in range(6):
        p = Thread(target = task1)
        p.start()
        list1.append(p)

    for p in list1:
        p.join()
        b = time.time()
    print(f'计算线程密集型消耗时间:{b -a}')

    #测试IO密集型
    a = time.time()
    list1 = []
    for line in range(6):
        p = Thread(target = task2)
        p.start()
        list1.append(p)

    for p in list1:
        p.join()
    b = time.time()
    print(f'IO线程密集型的消耗时间:{b - a}')
    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
计算进程密集型消耗的时间:0.3511178493499756
IO进程密集型消耗时间:3.215735912322998
计算线程密集型消耗时间:0.43486547470092773
IO线程密集型的消耗时间:3.003101110458374

以上是关于全局解释器和线程的主要内容,如果未能解决你的问题,请参考以下文章

python3多线程和GIL全局解释器所

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

GIL 相关 和进程池

全局解释器和线程

并发编程——GIL全局解释器锁死锁现象与递归锁信号量Event事件线程queue

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