并发编程-进~线程-01GIL全局解释器锁

一丶什么是GIL锁

python解释器有不少种 最多见的就是Cpython解释器
GIL本质也是一把互斥锁:将并发变成串行牺牲效率保证数据的安全
用来阻止同一个进程下的多个线程的同时执行(同一个进程内多个线程没法实现并行可是能够实现并发python

在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,没法利用多核优点安全

二丶为何存在GIL

GIL的存在是由于CPython解释器的内存管理不是线程安全的多线程

垃圾回收机制自己就是python解释器开启的一个进程必然除了主线程外还会有一个垃圾回收线程并发

GIL和垃圾回收机制

一个cpython开启进程中一定有一个解释器线程, 一个垃圾回收机制线程, 当前有一个变量a 等于1,就是申请一分内存空间,把1放进去,而后把a指向这个内存位置app

在这过程当中会出现这么一种状况: 当建立出 一个空间,把值为1放进去时候, 同时垃圾回收线程起来了,而后它扫描到a这个时候他尚未对值1对它进行绑定关系 ,垃圾回收机制判断它为一个无用的变量,而后把它删除了, 以后当要指向的操做时候,忽然发现没有了变量a, 这时候就出现了报错!测试

其实GIL的出现就是为了解决垃圾回收机制 , 让数据更加的安全!ui

它的存在会加把锁,好比当前 某线程抢到了GIL锁, 而后对变量进行建立绑定时候 别的线程(这边好比垃圾回收机制) 它抢不到当前的这把锁, 它会等待前个线程结束释放锁后强锁成功才会运行, 这样就不会出现刚才的那种临界状况.线程

两个常见的错误点

1.GIL是python的特色吗?code

不是! 它是CPython的特色!对象

2.单进程多个多个线程没法利用多核优点是全部语言的通病吗?

不是! 它只是全部解释型语言的通病,就好比 PHP丶 Python

三丶GIL和Lock

GIL保护的是解释器级的数据,保护用户本身的数据则须要本身加锁处理

gil锁

四丶python的多线程是否有用

研究python的多线程是否有用须要分状况讨论
四个任务 计算密集型的 10s
单核状况下
开线程更省资源
多核状况下
开进程 10s
开线程 40s

四个任务 IO密集型的
单核状况下
开线程更节省资源
多核状况下
开线程更节省资源

4.1测试代码

计算密集型

# 计算密集型
from multiprocessing import Process
from threading import Thread
import os,time
def work():
    res=0
    for i in range(100000000):
        res*=i


if __name__ == '__main__':
    l=[]
    print(os.cpu_count())  # 本机为6核
    start=time.time()
    for i in range(6):
        # p=Process(target=work) #耗时  4.732933044433594
        p=Thread(target=work) #耗时 22.83087730407715
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop=time.time()
    print('run time is %s' %(stop-start))

IO密集型

from multiprocessing import Process
from threading import Thread
import threading
import os,time
def work():
    time.sleep(2)

if __name__ == '__main__':
    l=[]
    print(os.cpu_count()) #本机为6核
    start=time.time()
    for i in range(4000):
        p=Process(target=work) #耗时9.001083612442017s多,大部分时间耗费在建立进程上
        # p=Thread(target=work) #耗时2.051966667175293s多
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop=time.time()
    print('run time is %s' %(stop-start))
python的多线程到底有没有用
须要看状况而定  而且确定是有用的

多进程+多线程配合使用

五丶pythonGIL锁

from threading import Thread
import time

n = 100

def task():
    global n
    tmp = n
    # time.sleep(1)
    n = tmp -1

t_list = []
for i in range(100):
    t = Thread(target=task)
    t.start()
    t_list.append(t)

for t in t_list:
    t.join()

print(n)

过程分析:全部线程抢的是GIL锁,或者说全部线程抢的是执行权限   线程1抢到GIL锁,拿到执行权限,开始执行,而后加了一把Lock,尚未执行完毕,即线程1还未释放Lock,有可能线程2抢到GIL锁,开始执行,执行过程当中发现Lock尚未被线程1释放,因而线程2进入阻塞,被夺走执行权限,有可能线程1拿到GIL,而后正常执行到释放Lock。。。这就致使了串行运行的效果 锁一般被用来实现对共享资源的同步访问。为每个共享资源建立一个Lock对象,当你须要访问该资源时,调用acquire方法来获取锁对象(若是其它线程已经得到了该锁,则当前线程需等待其被释放),待资源访问完后,再调用release方法释放锁:

相关文章
相关标签/搜索