python多线程学习(一)
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)。
考虑两种情况
- 计算密集:这时,几乎没一个线程都是执行满100tick后让出锁的,所以和单线程跑没啥区别,而且线程切换也需要时间,最终程序运行时间比起单线程反而更长。
- I/O密集型:一个线程只执行了几tick,遇见I/O阻塞。这时候代码已经解释过了,可以独立执行I/O过程,这是切换到另一个线程,同理。最终类似于真正的多线程,在I/O上节省的时间多余在线程切换消耗的时间,比单线程执行快。
因而,python多线程适合I/O密集型程序。
CPython 为什么要这样设计
多线程有个问题,怎么解决共享数据的同步、一致性问题?因为,对于多个线程访问共享数据时,可能有两个线程同时修改一个数据情况,如果没有合适的机制保证数据的一致性,那么程序最终导致异常,所以,Python之父就搞了个全局的线程锁,不管你数据有没有同步问题,反正一刀切,上个全局锁,保证数据安全,简单粗暴。
这种解决办法放在90年代,其实是没什么问题的,毕竟,那时候的硬件配置还很简陋,单核 CPU 还是主流,多线程的应用场景也不多,大部分时候还是以单线程的方式运行,单线程不要涉及线程的上下文切换,效率反而比多线程更高(在多核环境下,不适用此规则)。所以,采用 GIL 的方式来保证数据的一致性和安全,未必不可取,至少在当时是一种成本很低的实现方式。
解决方案
因为Cpython的GIL,使python的多线程显得鸡肋。可以试着使用别的解释器,但更常见的作法还是使用多进程。(当然,多进程必然消耗资源多一点)。
接下来学习
多线程主要用的是标准库中的threading包,thread基本不用(主要是它在主线程结束后,其他线程会直接停止,有点类似于守护进程,显然不安全)。
多进程使用标准库中的multiprocessing。
接下来几天阅读官方文档中的这几节。
python多线程学习(一)的更多相关文章
- python多线程学习记录
1.多线程的创建 import threading t = t.theading.Thread(target, args--) t.SetDeamon(True)//设置为守护进程 t.start() ...
- python 多线程学习小记
python对于thread的管理中有两个函数:join和setDaemon setDaemon:如果在程序中将子线程设置为守护线程,则该子线程会在主线程结束时自动退出,设置方式为thread.set ...
- python多线程学习二
本文希望达到的目标: 多线程同步原语:互斥锁 多线程队列queue 线程池threadpool 一.多线程同步原语:互斥锁 在多线程代码中,总有一些特定的函数或者代码块不应该被多个线程同时执行,通常包 ...
- Python多线程学习
一.Python中的线程使用: Python中使用线程有两种方式:函数或者用类来包装线程对象. 1. 函数式:调用thread模块中的start_new_thread()函数来产生新线程.如下例: ...
- python 多线程学习
多线程(multithreaded,MT),是指从软件或者硬件上实现多个线程并发执行的技术 什么是进程? 计算机程序只不过是磁盘中可执行的二进制(或其他类型)的数据.它们只有在被读取到内存中,被操作系 ...
- Python 多线程学习(转)
转自:http://www.cnblogs.com/slider/archive/2012/06/20/2556256.html 引言 对于 Python 来说,并不缺少并发选项,其标准库中包括了对线 ...
- Python多线程学习资料1
一.Python中的线程使用: Python中使用线程有两种方式:函数或者用类来包装线程对象. 1. 函数式:调用thread模块中的start_new_thread()函数来产生新线程.如下例: ...
- Python多线程学习笔记
Python中与多线程相关的模块有 thread, threading 和 Queue等,thread 和threading模块允许程序员创建和管理线程.thread模块提供了基本的线程和锁的支持,而 ...
- 《转》Python多线程学习
原地址:http://www.cnblogs.com/tqsummer/archive/2011/01/25/1944771.html 一.Python中的线程使用: Python中使用线程有两种方式 ...
随机推荐
- 11.EL(表达式语言)
一.EL概述 EL(Expression Language,表达式语言)是JSP2.0 中引入的新内容.通过EL可以简化在JSP中对对象的引用,从而规范页面代码,增加程序的可读性和可维护性. 1.EL ...
- 关于int main(int argc,char* argv[])详解
平时在VS的环境下,主函数总会看到这两个参数,今天突然很想知道这两个参数的原理以及作用,因此查了下资料.真心受教了. 下面的博文是在百度空间看一位大神的,原文链接:http://hi.baidu.co ...
- JVM之Java类加载机制
什么是类加载机制 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这既是虚拟机的类加载机制 类的生命周期 生命周期简述 ...
- CentOS7 安装JumpServer
环境: CentOS Linux release 7.6.1810 (Core) JumpServer 1.4.8 Python 3.6.X MariaDB 编译安装Python3.6 首先,下载Py ...
- ccf 201612-3 权限查询
ccf 201612-3 权限查询 解题思路: 建立一个二维矩阵存储权限和角色 还差30分emmm #include<iostream> #include<cstring> ...
- 5.Hiveguigun滚(ノ`Д)ノ竟然竞争谨慎谨慎谨慎哈喇子罢工八公
1.Hive简介 2.Hive部署与安装 3.Hive的使用 4.Hive JDBC编程
- leetcode常见算法与数据结构汇总
leetcode刷题之后,很多问题老是记忆不深刻,因此特意开此帖: 一.对做过题目的总结: 二.对一些方法精妙未能领会透彻的代码汇总,进行时常学习: 三.总结面试笔试常见题目,并讨论最优解法及各种解法 ...
- [go]go并发
同步协程 通过睡眠方法 // 通过睡眠方式等待 time.Sleep(time.Second) <-time.NewTimer(time.Second).C <-time.After(ti ...
- Cortex-M3 异常返回值EXC_RETURN
[EXC_RETURN] 在进入异常服务程序后,硬件自动更新LR的值为特殊的EXC_RETURN.当程序从异常服务程序返回,把这个EXC_RETURN值送往PC时,就会启动处理器的异常中断返回序列.因 ...
- 必会SQL笔试题
()表名:购物信息 购物人 商品名称 数量 A 甲 B 乙 C 丙 A 丁 B 丙 …… 给出所有购入商品为两种或两种以上的购物人记录 答:); ()表名:成绩表 姓名 课程 分数 张三 语文 张三 ...