ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

05-5 万字长文:实现多线程(结尾)

2021-06-12 18:02:30  阅读:165  来源: 互联网

标签:执行 GIL 05 进程 线程 字长 多线程 CPU


watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

 

5.6 Python 多线程的问题

你好,我是悦创。由于 Python 中 GIL 的限制,导致不论是在单核还是多核条件下,在同一时刻只能运行一个线程,导致 Python 多线程无法发挥多核并行的优势。

GIL 全称为 Global Interpreter Lock,中文翻译为全局解释器锁,「其最初设计是出于数据安全而考虑的。」

在 Python 多线程下,每个线程的执行方式如下:

  • 获取 GIL
  • 执行对应线程的代码
  • 释放 GIL

可见,某个线程想要执行,必须先拿到 GIL,我们可以把 GIL 看作是通行证,并且在一个 Python 进程中,GIL 只有一个。拿不到通行证的线程,就不允许执行。这样就会导致,即使是多核条件下,一个 Python 进程下的多个线程,同一时刻也只能执行一个线程。

不过对于爬虫这种 IO 密集型任务来说,这个问题影响并不大。而对于计算密集型任务来说,由于 GIL 的存在,多线程总体的运行效率相比可能反而比单线程更低。

5.7 避免 GIL

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

前面开头已经提到:因为 「GIL」 的存在,所以不管我们开了多少线程,同一时间始终只有一个线程在执行。那我们该如何避免 「GIL」 呢?

那这样的话,我们「不开线程」不就行,(它的的存在已经无法避免,那我们选择不使用它不就相当于不存在嘛)。那这是,你会想:那不开线程我们开啥呢?

问的好!

我们来开:「进程」,那怎么说?别急!请听我细细道来。

比方你有 「3 个 CPU」(当然,你可能有更多,这里就按 「3」 个 「CPU」来为例子),那我们就开 「3 个进程」就好。一个 「CPU」 上运行就好。

「Ps:我们的进程是可以同时运行的。」

我们可以看一下下面的图片:

「任务管理器」

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

我们 「任务管理」 上的每一项都是一个进程。

多进程比多线程不好的地方是什么呢?

多进程的创建和销毁开销也会更大,成本高。

你可能线程可以开许多的线程,但你的进程就是看你的 「CPU」 数量。

进程间无法看到对方数据,需要使用栈或者队列进行获取。

每个进程之间都是独立的。

就好像我们上面的谷歌浏览器和我们的 Pycharm 是没有任何关系的,谷歌浏览器上面的数据肯定不可能让 Pycharm 看到。这就是我们所说的进程之间的独立性。

如果你想要一个进行抓取数据,一个进行调用数据,那这时是不能直接调用的,需要你自己定义个结构才能使用。>>> 编程复杂度提升。


学员问题:任务管理器上面超过五六个进程。都是进程的话,怎么能开那么多呢?

答:我们一个 CPU 不止能执行一个进程,就比如我的一个 CPU 里面密麻麻有许多进程。(比方我现在开六个进程)并发执行的。只不过计算机执行的速度非常快,这里我简单讲一下哈。这是计算机原理的课。

不管是任何操作系统,现在就拿单核操作系统来说:我们假设现在只有一个 CPU ,一个 CPU 里面六个「进程」,同一时间它只有一个进程在运行。不过我们计算执行速度非常快,这个程序执行完,它就会执行一个「上下文切换」,执行下一个。(因为,它执行的速度非常快,你就会感觉是并发执行一样。)

实际上,一个 CPU 同一时间只有一个进程在执行,一个进程里面它只有一个线程在执行。(当然,这个单核是五六年前了。现在肯定至少有双核。

那就说有第二个 CPU 了。

而第二个和  CPU 上面又有许多个 「进程」,两个 「CPU」 是互不相干。

那这时候,第一个 CPU 上面运行一个进程,而我们的第二个 CPU 上面也有一个进程,两个是互补相干。 (就相当于你开了两台电脑。)

但是同一个 CPU 在同一时间只有一个就进程。(不管你(电脑)速度多么快,实际上本质上(在那一秒)只有一个进程在执行。「如果你是双核,那就有两个进程。(四核就有四个进程)」

Python 有个不好的地方,刚刚上面讲到,如果我们有两个 CPU 那就有两个进程在执行(那四个 CPU 就是四个进程在执行),**但是因为 Python 当中存在着 GIL,它即使有四个 CPU 每次也只有一个线程能进去,**也就是说:同一时间当中,一个 CPU 上的一个进程中的一个线程在执行。剩下的都不能运行,我们的 Python 不能利用多核。

如果,大家用的是 C、Java、Go 这种的就没有这个说法了。

5.8 线程池

我找了许多包,这个包还是不错的:Pip install threadpool

# project = 'Code', file_name = '线程池', author = 'AI悦创'
# time = '2020/3/3 0:05', product_name = PyCharm
# code is far away from bugs with the god animal protecting
# I love animals. They taste delicious.

import time
import threadpool

# 执行比较耗时的函数,需要开多线程
def get_html(url):
time.sleep(3)
print(url)
# 按原本的单线程运行时间为:300s
# 而多线程池的化:30s
# 使用多线程执行 telent 函数
urls = [i for i in range(100)]
pool = threadpool.ThreadPool(10) # 建立线程池

# 提交任务给线程池
requests = threadpool.makeRequests(get_html, urls)

# 开始执行任务
for req in requests:
pool.putRequest(req)
pool.wait()

 

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

 

标签:执行,GIL,05,进程,线程,字长,多线程,CPU
来源: https://blog.51cto.com/aiyc/2899200

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有