学习python的进程和线程以来,对这两个概念一直都处于模糊状态,所以决定花点时间好好学习一下这块知识。以下是我自己在学习过程中形成的一些疑问以及搜集的一些相应的比较好的答案,整理如下,方便复习自查。

我们可能听过这样的说法:由于GIL的存在,在多个CPU情况下python的多线程是个鸡肋的存在。至于为什么会这样,下文转载的一篇博文中有比较详细的解说。

虽然python多线程鸡肋,但是在阅读python cookbook相关章节时,看到这么样的描述:“GIL带来的最明显的影响就是多线程的python程序无法充分利用多个CPU核心带来的优势(即,一个采用多线程技术的计算密集型应用只能在一个CPU上运行.....如果我们的程序主要是在做I/O操作,比如处理网络连接,那么选择多线程技术常常是一个明智选择。因为他们大部分时间都花在等待对方连接上了)”(来自python cookbook中文版第三版12.9小节,如何规避GIL带来的限制)。其实对于这句话的理解,同样在下面转发的博文中有解释,这里只是用一个更权威的描述来佐证博文中的论述。

所以说,多个CPU情况下,对于I/O密集型操作,使用多线程技术是有益无害的,但是,一旦某个线程是CPU密集型操作,那么该线程就可能长时间占用GIL,导致其他线程长期等待,也无法发挥多个CPU带来的优势,此时应该尽量使用多进程,而不是多线程。既然python多线程仍有用武之地,所以还是有必要好好学习一下这块知识。

I/O操作是否会一直占用CPU?

这个问题在刚开始学习python线程和五大I/O模型的时候困惑了我一段时间,因为我的认识中,所有程序都是由CPU由上到下一条一条执行的。但是在学习I/O模型时,比如下图的异步I/O模型,图左侧aio_read函数发出一个system call之后就return了,然后CPU接着搞事情,但是同时图右侧又注明wait for data,什么鬼,谁在等?难道CPU能分身不成?虽然猜测应该是有别的外设(好在曾经搞过嵌入式,知道外设这概念)在处理数据发送和接收,然后通过中断通知CPU处理结果,但是没有正经理论支撑还是放心不下,于是知乎了一下,果然还是得到了比较满意的答案,总的来说就是IO所需要的CPU资源非常少。大部分工作是分派给DMA(Direct Memory Access)直接内存存取完成的。我把知乎该条回答复制到了我的博客园,以便复习查看点击这里

明白了这个,也就明白了CPU密集型和I/O密集型在使用线程中的区别,CPU密集型代码段需要一直占用CPU,而I/O密集型代码,可以在进行I/O操作的时候让出CPU控制权,而I/O操作的过程是交给DMA处理的,并不需要CPU直接参与。

多核处理器,一个进程的多个线程能否在不同CPU中并行运行?

之前一直以为多核处理器每个CPU只能并行执行不同的进程,因为进程是资源分配的最小单位,如果一个进程的不同线程运行在不同CPU,那么线程间通讯应该比较困难,后来觉得如果这样的话,一个进程的多个线程只能在同一个CPU下轮流执行,对于任务不多的情况下,会导致其他CPU在那里空转,实在是浪费资源,百度了很久,都没有得到正面的回答,在StackOverflow上得到一个好一点的回答。

先把结论摆出来,那就是:同一进程的多个线程,是可以在不同CPU并行(不是并发)执行的。形象一点就是说,假设有一个进程的两个线程A和B,以及两个核CPU1和CPU2,操作系统可以把线程A分配给CPU1执行,同时线程B分配给CPU2执行,以达到并发执行的效果。

原文地址点击这里

上面两个回答来自同一个提问,简单概括一下第一个回答,意思就是一个包含多个线程的进程,操作系统会决定哪个线程在哪个CPU执行(通过机智的试探法来提升负载平衡和优化能耗等)。第二个回答大概意思是,”操作系统不太在意线程来自哪个进程,它通常把线程安排给不同核的处理器,不管线程来自哪个进程,这可以使得一个进程的四个线程在同一时刻运行“。

python的GIL全局锁是什么,为什么说它导致了python多线程的鸡肋,如何规避这种不利影响?

本来是打算自己查资料做实验总结的,后来发现这个话题已经有相当多优秀的博文可供参考,看着别人的文章,发现自己重新造轮子有点多此一举,而且不自信能写出人家的深度,不如直接拿来主义,哦不,是借鉴参考一下。果不其然,有时候做做伸手党,还是emmm......真香...。

好了,直接放上一篇看完很受益的博文的链接,方便以后复习时查看。

博文链接

关于该博文中说到的不执行任何I/O操作的CPU密集型线程,会一直占用GIL,导致其他I/O密集型线程进入无尽的等待,这个说法应该是值得商榷的,在看《python cookbook》12.9.2章节的时候,页脚有这么一段注释,我把它贴出来:

也就是说,当CPU密集型线程占用GIL后,python解释器在执行了一定数量的python代码后会主动释放GIL,以便让其他线程得到执行的机会,所以博文中所述的CPU密集型线程会一直占用GIL的说法是有疑点的,不过博文中是使用的python2,而cookbook是基于python3。

python多线程一些知识点梳理的更多相关文章

  1. day-3 python多线程编程知识点汇总

    python语言以容易入门,适合应用开发,编程简洁,第三方库多等等诸多优点,并吸引广大编程爱好者.但是也存在一个被熟知的性能瓶颈:python解释器引入GIL锁以后,多CPU场景下,也不再是并行方式运 ...

  2. python多线程相关知识点

    1. 信号量 信号机维护着一个计数器,指定可同时访问资源或者进入临界区的线程数.每次有一个线程获得信号机时,计数器-1.若计数器为0,其他线程就停止访问信号机 Semphore,是一种带计数的线程同步 ...

  3. Java多线程入门知识点梳理

    前言 在多核时代,高并发时代,对系统并行处理能力有很高要求.多线程就是这个时代最好的产物.通过使用多线程可以增强系统并行处理能力,提高CPU资源的有效利用:从而提高系统的处理能力.常见应用场景如:多窗 ...

  4. Python多线程Selenium跨浏览器测试

    前言 在web测试中,不可避免的一个测试就是浏览器兼容性测试,在没有自动化测试前,我们总是苦逼的在一台或多台机器上安装N种浏览器,然后手工在不同的浏览器上验证主业务流程和关键功能模块功能,以检测不同浏 ...

  5. 搞定python多线程和多进程

    1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...

  6. python多线程和多进程

    1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...

  7. [转]Python多线程与多线程中join()的用法

    https://www.cnblogs.com/cnkai/p/7504980.html Python多线程与多进程中join()方法的效果是相同的. 下面仅以多线程为例: 首先需要明确几个概念: 知 ...

  8. 【Python】详解Python多线程Selenium跨浏览器测试

    前言 在web测试中,不可避免的一个测试就是浏览器兼容性测试,在没有自动化测试前,我们总是苦逼的在一台或多台机器上安装N种浏览器,然后手工在不同的浏览器上验证主业务流程和关键功能模块功能,以检测不同浏 ...

  9. python 多线程示例

    原文链接:http://www.cnblogs.com/whatisfantasy/p/6440585.html 1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的 ...

随机推荐

  1. Mac查看进程

    Last login: Tue Jun 11 11:18:10 on ttys001 liangyufengdeMacBook-Pro:vod-admin liangyufeng$ lsof -i:6 ...

  2. mysql 字段添加以及删除

    mysql> select * from user; +------+-----------+-----------+ | id | name | address | +------+----- ...

  3. mysql cos() 函数

    mysql> ); +--------------------+ | cos(PI()/) | +--------------------+ | 0.5000000000000001 | +-- ...

  4. firewalld添加/删除服务service,端口port

    启动CentOS/RHEL 7后,防火墙规则设置由firewalld服务进程默认管理. 一个叫做firewall-cmd的命令行客户端支持和这个守护进程通信以永久修改防火墙规则. # firewall ...

  5. 把pdf的内容转化为txt文件

    import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.util.PDFTextStripper; import j ...

  6. Hive(一)—— 启动与基本使用

    一.基本概念 Hive用于解决海量结构化日志的数据统计问题. Hive是基于Hadoop的一个数据仓库工具.本质是将HQL(Hive的查询语言)转化成MapReduce程序. HIve处理的数据存储在 ...

  7. 013 Enhancer创建动态代理

    在上一章使用了Enhancer,没有仔细说明代理的问题,在这一章进行详细的说明. 原本想使用cf包的,后来发现使用framework包下的包也没有问题,程序中就一直使用framework中的类. 一: ...

  8. 【NumPy】 之常见运算(np.around、np.floor、np.ceil、np.where)

    aroundnp.around 返回四舍五入后的值,可指定精度. around(a, decimals=0, out=None) a 输入数组 decimals 要舍入的小数位数. 默认值为0. 如果 ...

  9. 2-4 【接口Interface Flex布局】让顶部导航滚动

    可以把复杂的类型做命名.例如接口中没有定义年龄,在定义person的时候 如果写了age那么就会报错.因为我们接口中并没有定义年龄. 可选属性,只读属性 新的布局方式 下面这里menu设置类型为Top ...

  10. knuth洗牌算法

    首先来思考一个问题: 设计一个公平的洗牌算法 1. 看问题,洗牌,显然是一个随机算法了.随机算法还不简单?随机呗.把所有牌放到一个数组中,每次取两张牌交换位置,随机 k 次即可. 如果你的答案是这样, ...