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中使用线程有两种方式 ...
随机推荐
- MySQL_(Java)提取工具类JDBCUtils
MySQL_(Java)使用JDBC向数据库发起查询请求 传送门 MySQL_(Java)使用JDBC创建用户名和密码校验查询方法 传送门 MySQL_(Java)使用preparestatement ...
- 如何卸载zabbix且删除
1.彻底卸载zabbix和删除残留文件 1 2 [root@localhost etc]# service zabbix stop //这个命令是停止服务 [root@localhost et ...
- R-aggregate()
概述 aggregate函数应该是数据处理中常用到的函数,简单说有点类似sql语言中的group by,可以按照要求把数据打组聚合,然后对聚合以后的数据进行加和.求平均等各种操作. x=data.fr ...
- HNOI2012矿场搭建
做完Mining Your Own Business后觉得这个题没什么意思了,数据范围小的连边数不清空都能A. 题解直接看这篇吧.做题的经历也挺……对吧. #include<iostream&g ...
- 软工团队Git现场编程实战
组员职责分工 成员 分工 鲍子涵 分配职责,整合代码 吴宜航 UI设计与实现 钟博 UI设计与实现(Main Coder) 黄海东 数据整理 王镇隆 前端api接口分析和使用(Main Coder) ...
- koa 基础(十八)es6中的类、静态方法、继承
1.app.js /** * es6中的类.静态方法.继承 */ // 定义Person类 class Person { constructor(name, age) { /*类的构造函数,实例化的时 ...
- koa 基础(十四)cookie 的基本使用
1.app.js /** * cookie的简介: * 1.cookie保存在浏览器客户端 * 2.可以让我们用同一个浏览器访问同一个域名的时候共享数据 * * cookie的作用: * 1.保存用户 ...
- js版的虚线框
要求:实现鼠标点击面板的一个点,拖动到固定的位置,出现虚线框 样图: 具体的代码实现: js文件 <script> window.onload = function(){ docu ...
- Nginx作为静态资源web服务
一.CDN 1.定义: 内容分发的逻辑网络. 2.作用: CDN能做到传输延时的最小化. CDN请求示意图如下: 二.静态资源需要配置的一些语法模块. 1.配置语法 - 文件读取 Syntax : s ...
- RzPageControl(pagecontrol)实现多标签的动态添加,切换,关闭
https://blog.csdn.net/pdw2009/article/details/76157651 使用RzPageControl来实现多标签页使用菜单来打开标签页,通过标签页的captio ...