当前位置:   article > 正文

Python--GIL锁_python中的gil锁

python中的gil锁

一、进程与线程

1.进程

操作系统进行资源分配和调度的基本单位,多个进程之间相互独立。

2.线程

CPU进行资源分配和调度的基本单位,线程是进程的一部分,是比进程更小的能独立运行的基本单位,一个进程下的多个线程可以共享进程的多个资源。

二、GIL锁

1、GIL定义

全局解释器锁,简单来说是一个互斥锁,每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码。

2、GIL的准则

1)当前执行线程必须持有GIL

2)当线程遇到 IO的时、时间片到时或遇到阻塞时, 会释放GIL(Python 3.x使用计时器----执行时间达到阈值后,当前线程释放GIL,或Python 2.x,tickets计数达到100。)

三、多线层不能充分利用多核GPU的优势

1、CPU密集采用多进程,假如IO操作少,用多线程的话,因为线程共享一个全局解释器锁,当前运行的线程会霸占GIL,其他线程没有GIL,就不能充分利用多核CPU的优势。

计算密集型--采用多进程(耗时2秒左右)

  1. from multiprocessing import Process
  2. import time
  3. from threading import Thread
  4. def foo():
  5. res = 1.1
  6. for i in range(1, 100000000):
  7. res *= i
  8. if __name__ == '__main__':
  9. l = []
  10. start_time = time.time()
  11. for i in range(8):
  12. p = Process(target=foo)
  13. p.start() # 启动进程,并调用该子进程中的p.run(),p.run()调用target指定的函数
  14. l.append(p)
  15. for p in l:
  16. p.join() # 主进程等待所有子进程p执行完毕,才执行
  17. print(time.time() - start_time)

计算密集型--采用多线程(耗时37秒) 

  1. from multiprocessing import Process
  2. import time
  3. from threading import Thread
  4. def foo():
  5. res = 1.1
  6. for i in range(1, 100000000):
  7. res *= i
  8. if __name__ == '__main__':
  9. l = []
  10. start_time = time.time()
  11. for i in range(8):
  12. p = Thread(target=foo)
  13. p.start()
  14. l.append(p)
  15. for p in l:
  16. p.join()
  17. print(time.time() - start_time)

2、IO操作密集采用多线程,在用户输入,sleep的时候,可以切换到其他线程执行,减少等待时间。常见IO密集型任务:网络IO(抓取网页数据)、磁盘操作(读写文件)、键盘输入。

IO密集型--采用多进程(耗时19秒)

  1. def foo():
  2. time.sleep(2) # IO操作时会释放CPU -- CPU大多数时间是处于闲置状态,频繁的切换
  3. if __name__ == '__main__':
  4. l = []
  5. start_time = time.time()
  6. for i in range(1000):
  7. p = Process(target=foo)
  8. p.start()
  9. l.append(p)
  10. for p in l:
  11. p.join()
  12. print(time.time() - start_time)

 IO密集型--采用多线程(耗时2秒) 

  1. def foo():
  2. time.sleep(2)
  3. if __name__ == '__main__':
  4. l = []
  5. start_time = time.time()
  6. for i in range(1000):
  7. p = Thread(target=foo)
  8. p.start()
  9. l.append(p)
  10. for p in l:
  11. p.join()
  12. print(time.time() - start_time)

四、总结

1、对于IO密集型应用,即使有GIL存在,由于IO操作会导致GIL释放,其他线程能够获得执行权限。由于多线程的通讯成本低于多进程,因此偏向于使用多线程。

2、对于计算密集型应用,由于CPU一直处于被占用,GIL锁直到规定时间才会释放,然后才会切换状态,导致多线程处于绝对的劣势,此时可以采用多进程+协程。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/687146
推荐阅读
相关标签
  

闽ICP备14008679号