python多线程、多进程 初探

原先刚学Java的时候,多线程也学了几天,后来一直没用到。然后接触python的多线程的时候,貌似看到一句”python多线程很鸡肋“,于是乎直接跳过了多线程的学习。

接触爬虫,才开始用到多进程这个东西。

既然用到了,就系统地学吧。先来python的,再总结一下Java的。

什么是线程和进程

很经典的一个解释是“进程是资源分配的最小单位,线程是CPU调度的最小单位“。
比如我们在任务管理器中看到的就是进程,例如qq.exe,qq就是一个进程。打开qq后,启动多条线程,各自负责文件下载、更新朋友圈、聊条等功能。

每个进程,都有自己的地址空间、内存、数据栈以及其他用于跟踪执行的辅助数据。进程可以通过派生(fork或spawn)新的进程来执行其他任务,不过这个新的进程是独立的,所有进程之间只能采用IPC(进程间通信)的方式共享信息。

线程,于进程类似,有时候也称为轻量级进程,可以把他们 视为一个主进程中并行运行的一些”迷你进程“。同一个进程下的线程共享资源。
以前单核CPU时代,多线程用处并不多。进程和线程没法做到真正的并行运算,而如今多核时代,真正能实现多条线程一起跑。

线程于进程的对比

对比维度 进程 线程
数据共享、同步 IPC共享数据较复杂,同步简单 同进程下线程数据共享,但同步复杂
可靠性 进程间互相独立 一个线程坏掉可能使整个进程挂掉
资源消耗 独立资源,消耗多。进程间切换慢 切换快,共享资源,资源消耗少

总结,进程和线程还可以类比为火车和车厢:

线程在进程下行进(单纯的车厢无法运行)

一个进程可以包含多个线程(一辆火车可以有多个车厢)

不同进程间数据很难共享(一辆火车上的乘客很难换到另外一辆火车,比如站点换乘)

同一进程下不同线程间数据很易共享(A车厢换到B车厢很容易)

进程要比线程消耗更多的计算机资源(采用多列火车相比多个车厢更耗资源)

进程间不会相互影响,一个线程挂掉将导致整个进程挂掉(一列火车不会影响到另外一列火车,但是如果一列火车上中间的一节车厢着火了,将影响到该趟火车的所有车厢)

进程可以拓展到多机,进程最多适合多核(不同火车可以开在多个轨道上,同一火车的车厢不能在行进的不同的轨道上)

进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。(比如火车上的洗手间)-”互斥锁(mutex)”

进程使用的内存地址可以限定使用量(比如火车上的餐厅,最多只允许多少人进入,如果满了需要在门口等,等有人出来了才能进去)-“信号量(semaphore)”

p ython的多线程为何鸡肋

因为GIL,全局解释锁机制,python的多线程是伪多线程。

准确来说,GIL并不是python的机制,而是CPython解释器(主流解释器)的机制(比如Jpython就没有GIL)。

什么是GIL

其实有点类似于单核CPU执行多进程的过程,虽然可以有多个进程,但只有一个CPU啊,一个进程执行的时候别的进程只能等,只是快速切换执行感觉上是一起执行罢了。现在多核CPU能做到真正的并行

在 Cpython 解释器(Python语言的主流解释器)中,有一把全局解释锁(Global Interpreter Lock),在解释器解释执行 Python 代码时,先要得到这把锁。锁只有一把,一个线程执行的时候,别的线程也得等,多核CPU也没用。(真正的多线程,比如Java的多线程,在多核情况下,可以实现真正的多条线程同步运行)

1.设置GIL

2.切换到一个线程去执行

3.运行

指定数量的字节码指令

线程主动让出控制(可以调用time.sleep(0))

4.把线程设置完睡眠状态

5.解锁GIL

6.再次重复以上步骤

线程什么时候会让出全局锁呢?一是执行满 100 tick(可以理解为100单位的指令),二是遇见了阻塞(比如I/O)。

考虑两种情况

  1. 计算密集:这时,几乎没一个线程都是执行满100tick后让出锁的,所以和单线程跑没啥区别,而且线程切换也需要时间,最终程序运行时间比起单线程反而更长。
  2. I/O密集型:一个线程只执行了几tick,遇见I/O阻塞。这时候代码已经解释过了,可以独立执行I/O过程,这是切换到另一个线程,同理。最终类似于真正的多线程,在I/O上节省的时间多余在线程切换消耗的时间,比单线程执行快。

因而,python多线程适合I/O密集型程序。

CPython 为什么要这样设计

多线程有个问题,怎么解决共享数据的同步、一致性问题?因为,对于多个线程访问共享数据时,可能有两个线程同时修改一个数据情况,如果没有合适的机制保证数据的一致性,那么程序最终导致异常,所以,Python之父就搞了个全局的线程锁,不管你数据有没有同步问题,反正一刀切,上个全局锁,保证数据安全,简单粗暴。

这种解决办法放在90年代,其实是没什么问题的,毕竟,那时候的硬件配置还很简陋,单核 CPU 还是主流,多线程的应用场景也不多,大部分时候还是以单线程的方式运行,单线程不要涉及线程的上下文切换,效率反而比多线程更高(在多核环境下,不适用此规则)。所以,采用 GIL 的方式来保证数据的一致性和安全,未必不可取,至少在当时是一种成本很低的实现方式。

解决方案

因为Cpython的GIL,使python的多线程显得鸡肋。可以试着使用别的解释器,但更常见的作法还是使用多进程。(当然,多进程必然消耗资源多一点)。

接下来学习

多线程主要用的是标准库中的threading包,thread基本不用(主要是它在主线程结束后,其他线程会直接停止,有点类似于守护进程,显然不安全)。

多进程使用标准库中的multiprocessing。

接下来几天阅读官方文档中的这几节。

python多线程学习(一)的更多相关文章

  1. python多线程学习记录

    1.多线程的创建 import threading t = t.theading.Thread(target, args--) t.SetDeamon(True)//设置为守护进程 t.start() ...

  2. python 多线程学习小记

    python对于thread的管理中有两个函数:join和setDaemon setDaemon:如果在程序中将子线程设置为守护线程,则该子线程会在主线程结束时自动退出,设置方式为thread.set ...

  3. python多线程学习二

    本文希望达到的目标: 多线程同步原语:互斥锁 多线程队列queue 线程池threadpool 一.多线程同步原语:互斥锁 在多线程代码中,总有一些特定的函数或者代码块不应该被多个线程同时执行,通常包 ...

  4. Python多线程学习

    一.Python中的线程使用: Python中使用线程有两种方式:函数或者用类来包装线程对象. 1.  函数式:调用thread模块中的start_new_thread()函数来产生新线程.如下例: ...

  5. python 多线程学习

    多线程(multithreaded,MT),是指从软件或者硬件上实现多个线程并发执行的技术 什么是进程? 计算机程序只不过是磁盘中可执行的二进制(或其他类型)的数据.它们只有在被读取到内存中,被操作系 ...

  6. Python 多线程学习(转)

    转自:http://www.cnblogs.com/slider/archive/2012/06/20/2556256.html 引言 对于 Python 来说,并不缺少并发选项,其标准库中包括了对线 ...

  7. Python多线程学习资料1

    一.Python中的线程使用: Python中使用线程有两种方式:函数或者用类来包装线程对象. 1.  函数式:调用thread模块中的start_new_thread()函数来产生新线程.如下例: ...

  8. Python多线程学习笔记

    Python中与多线程相关的模块有 thread, threading 和 Queue等,thread 和threading模块允许程序员创建和管理线程.thread模块提供了基本的线程和锁的支持,而 ...

  9. 《转》Python多线程学习

    原地址:http://www.cnblogs.com/tqsummer/archive/2011/01/25/1944771.html 一.Python中的线程使用: Python中使用线程有两种方式 ...

随机推荐

  1. HDU 5113 Black And White ( 2014 北京区预赛 B 、搜索 + 剪枝 )

    题目链接 题意 : 给出 n * m 的网格.要你用 k 种不同的颜色填给出的网格.使得相邻的格子颜色不同.若有解要输出具体的方案 分析 : 看似构造.实则搜索.手构构半天没有什么好想法 直接搜就行了 ...

  2. linux下源码安装mariadb

    1.mariadb源码包下载地址:https://downloads.mariadb.org/ 2.安装mariadb是依赖包,创建mysql用户和目录: 命令  yum -y install rea ...

  3. PHP-windows下安装

    下载 Apache下载地址:http://httpd.apache.org/download.cgi PHP下载地址:http://php.net/downloads.php 解压 解压到安装路径下H ...

  4. JVM-GC算法(一)-标记清除算法

    首先,我们得知道根搜索算法,它可以解决我们应该回收哪些对象的问题,但是它显然还不能承担垃圾搜集的重任,因为我们在程序(程序也就是指我们运行在JVM上的JAVA程序)运行期间如果想进行垃圾回收,就必须让 ...

  5. EBS GL 日记账行“账户说明”段说明显示不全

    问题描述: 路径:总帐管理超级用户/日记帐/输入 如下图所示,日记账行的“账户说明字段”段值说明显示不全 解决方法: 路径:总帐管理超级用户/设置/财务系统/弹性域/关键字/段 如下图所示,找到相应的 ...

  6. Sql语法树示例 select username, ismale from userinfo where age > 20 and level > 5 and 1 = 1

    select username, ismale from userinfo where age > 20 and level > 5 and 1 = 1 --END-2019年9月5日17 ...

  7. 转贴 使用正则表达式解析一般sql语句(C++)

    https://blog.csdn.net/dreamgchuan/article/details/47715743 --END--2019年9月5日11点58分

  8. DP----鬼畜的数字三角形

    数字三角形 1   洛谷   P1216  数字金字塔 我们可以用 f [ i ] [ j ] 表示从(1,1)出发,到达(i,j)的最大权值和. (i , j)可以由 正上(i - 1 , j)或者 ...

  9. Tooltip 文字提示

    常用于展示鼠标 hover 时的提示信息. 基础用法 在这里我们提供 9 种不同方向的展示方式,可以通过以下完整示例来理解,选择你要的效果. 使用content属性来决定hover时的提示信息.由pl ...

  10. Mongdb、Mysql、Redis、Memcache场景

    个人的一点理解,不确定一定准确,有不对处欢迎指出 全部数据使用mysql存储,确保安全.准确和持久 大数据.非安全性数据使用Mongodb 小数据.结构丰富.持久化(主从数据)使用redis 小数据. ...