python多线程并发_Python进阶记录之基础篇(二十四)
回顾
在Python进阶记录之基础篇(二十三)中,我们介绍了进程的基本概念以及Python中多进程的基本使用方法。其中,需要重点掌握多进程的创建方法、进程池和进程间的通信。今天我们讲一下Python中的多线程。
线程的基本概念
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一个进程可以拥有多个并发的执行线索,这些执行线索也被称为可以获得CPU调度的执行单元,这就是所谓的线程。
由于线程在同一个进程下,因此它们可以共享相同的上下文。相对于进程而言,线程间的信息共享和通信也就更加容易。
当然在单核CPU系统中,真正的线程并发是不可能的,因为在某个时刻能够获得CPU的只有唯一的一个线程,多个线程共享了CPU的执行时间。
Python中的多线程
我们在之前内容中提到过,Python实现并发编程有三种方式,多进程是其中的一种,而多线程也是其中的一种。Python中实现多线程有两个模块:早期的thread模块(现在名为_thread)和目前主流的threading模块。
其中,thread是Python早期版本中处理多线程的模块,过于底层,而且很多功能都没有提供,属于低级模块。因此,我们现在主要使用的是比较高级的threading模块,threading模块对thread模块进行了封装,尤其是对多线程编程提供了更好的面向对象的封装。
现在,我们把上一节内容中下载文件的例子用多线程的方式来实现并发下载。

多线程
上述代码中,我们直接使用threading模块的Thread类来创建线程。与多进程类似,也是传入两个属性:target目标函数,args目标函数所需参数。然后调用start( )方法启动线程,调用join( )方法等待线程结束继续执行。
我们说过,threading模块对多线程编程提供了更好的面向对象的封装。因此,对于线程的创建,我们通常是定义一个继承自Thread类的子类。

面向对象的多线程
我们首先定义一个类,让它继承自Thread,然后重写Thread类中的run( )方法。当类的实例对象调用start( )方法时,就会触发这个run( )方法,因此我们会把线程要处理的代码放在run( )方法中。
线程锁Lock
多线程和多进程最大的不同在于,在多进程中,同一个变量,每个进程都各自有一份拷贝,彼此之间互不影响,而在多线程中,每个变量都由所有线程共享。因此,任何一个变量都可以被任何一个线程修改。
我们来看这样一个例子:将一个共享变量封装成一个类,然后自定义一个线程类,执行的功能是给共享变量加1,我们创建100个线程,并发执行,来看看结果。

多线程同时操作变量
运行上述代码我们发现,运行结果并不是我们预计的100,而是比100要小得多。之所以出现这种情况,是因为多个线程并发执行时,有可能会一起执行到new_data = self.__data + change这行代码,而每个线程得到的共享变量初始值都是self.__data = 0,都是在0上面做了加1的操作。
举个例子,现在线程1和线程2同时执行到加1操作,但由于两个线程得到的初始数据都是0,因此从结果上来看,总共只加了1。这就是为什么我们最后得到的是错误的结果。
线程之间共享数据虽然简单,但最大的危险就在于多个线程同时改一个变量,会把内容改乱。如果我们要确保上述共享变量data的正确性,就需要在change_data( )中上一把锁,这就是所谓的线程锁。
当某个线程开始执行change_data( )方法时,我们说,该线程此时获得线程锁,那么其他线程将无法同时执行change_data( )方法,只能等待当前线程释放线程锁后,才能获得线程锁进行修改。由于线程锁只有一个,无论多少线程,同一时刻最多只有一个线程持有该锁,所以,不会造成修改的冲突。
Python中创建线程锁通过threading模块的Lock( )方法来实现。

线程锁Lock
当多个线程同时执行到lock.acquire( )方法时,只有一个线程能成功地获取线程锁,然后继续执行代码,其他线程就只能继续等待直到获得线程锁为止。获得线程锁的线程用完后一定要释放锁,否则那些苦苦等待锁的线程将永远等待下去,成为死线程。因此我们使用try...finally来确保线程锁一定会被释放。可以看到,当我们加上线程锁后,运行结果就正确了。
线程锁的好处是确保了某段关键代码只能由一个线程从头到尾完整地执行,从而避免共享数据混乱。当然,这样做也是有代价的,首先是阻止了多线程的并发执行,包含线程锁的某段代码实际上只能以单线程模式执行,我们在执行代码的过程中就能感受到,加了线程锁的程序执行时间会明显增加,效率就大大地下降了。其次,当使用多个线程锁时,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁,导致多个线程全部挂起,既不能执行,也无法结束,只能靠操作系统强制终止。
此外,Python的多线程无法发挥CPU的多核特性,因为Python的解释器有一个“全局解释器锁”的东西,我们称之为GIL锁,任何线程执行前必须先获得GIL锁。每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行,使我们看上去像是在一起执行一样。不过即使如此,在Python中使用多线程依然能提升执行效率。
总结
以上内容介绍了线程的基本概念以及Python中多线程的使用方法,需要重点掌握多线程的创建和使用、理解线程锁的意义并能正确使用它。最后,我们总结一下Python实现并发编程的三种方式:多进程、多线程、多进程+多线程。感谢大家的支持与关注,欢迎一起学习交流~
相关文章:

awk处理文件内容格式
今天运营出了点问题,需要对特定时间段充值数做一个处理,文件格式有特定要求,要符合erlang的格式{roleID,gold}.mysql导出所有数据结果如下【取部分数据看】:kuwo 4 50004106230500 100kuwo 4 50004106230900 …

QQ远程协助没动静?QQ版本有讲究
一位网友觉得电脑反应速度慢了,想通过QQ远程协助让我处理一下。不料接受请求后,等了许久都显示网友电脑的桌面,而网友那边QQ也没有任何提示。 反复尝试了几次都是如此。 询问网友得知他用的QQ为2011版,而我使用的QQ是2008版。难…

java课堂测试样卷-----简易学籍管理系统
程序设计思路:分别建立两个类:ScoreInformation类(用来定义学生的基本信息以及设置set和get函数)ScoreManagement类(用来定义实现学生考试成绩录入,考试成绩修改,绩点计算等功能的函数)和一个主…
python3安装setuptools步骤_setuptools、pip的安装
第2篇分享 安装setuptools 下载setuptools源码setuptools-25.2.0.tar.gz选择需要的版本 这是一个压缩文件,将其解压到桌面,并进入该文件夹 按住shift键后,在文件夹空白处点击鼠标右键,选择:在此处打开命令窗重点&#…

如何将简单CMS后台管理系统示例转换为Java、Php等不同后台语言的版本
等下要去坐车,今天就不继续唠叨开发过程了,来谈一下普遍比较关心的后台语言问题。学习Ext JS,笔者一直强调学习的中心思路是“界面与数据是分离”。只要好好掌握这个思路,深入了解Ext JS的运作过程,就不会为后台语言使…

[面试]future模式
Future模式 什么是future模式? 传统单线程环境下,调用函数是同步的,必须等待程序返回结果后,才可进行其他处理。 Futrue模式下,调用方式改为异步。 Futrue模式的核心在于:充分利用主函数中的等待时间,利用…

java ide
tidespringsource sts a vmware product plugin:Aptana Studio 3(集成了Git) Run on Jettyeclipse for jee plugin:JBoss Tools,m2eclipe,spirng tools,svn

成长秘笈:是你教我,不是我教你
郑昀 20180622 “谢谢你,你是第一个面试的时候跟我说这么详细的。那我到你们公司之后怎么就能成长了呢?” “你们这些人最大的问题是出不了方案。 为什么出不了方案? 因为没有养成深度思考问题的习惯。 实现方案、算法、数据迁移、准备数据、…

计算机网络面试题(一)
1、OSI,TCP/IP,五层协议的体系结构,以及各层协议 OSI分层 (7层):物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。 TCP/IP分层(4层):网络接口 网络层、运…

Ubuntu下安装和配置Apache2
在Ubuntu中安装apache 安装指令:sudo apt-get install apache2 安装结束后: 产生的启动和停止文件是:/etc/init.d/apache2 启动:sudo apache2ctl -k start 停止:sudo apache2ctl -k stop 重新启动:sudo apa…

苹果电脑安装python3密码_mac系统安装Python3初体验
前沿 对于iOS开发不要随便拆卸系统自带的Python,因为有很多 library 还是使用 Python2.7。 1 安装Xcode 1.1 App Store 搜索Xcode 并安装 1.2 安装 Xcode command line tool 1.2.1 打开命令行terminal工具 control space 输入terminal 回车 1.2.2 安装Xcode command line tool…

【IBM Tivoli Identity Manager 学习文档】3 系统部署
作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/ ITIM 5.0 单服务器配置和部署。 部署ITIM之前要对其组件进行部署: IBM DB2 Enterprise 9.1 with FP2 IBM WebSphere Application Server 6.1 with FP9 IBM Tivoli Directory Server 6.2 IB…

数据结构Java版之红黑树(八)
红黑树是一种自动平衡的二叉查找树,因为存在红黑规则,所以有效的防止了二叉树退化成了链表,且查找和删除的速度都很快,时间复杂度为log(n)。 什么是红黑规则? 1.根节点必须是黑色的。 2.节点颜色要么是红要么是黑。 3.…

你真的了解Grid布局吗?
Grid网格布局 概述:Grid将容器划分为一个个网格,通过任意组合不同的网格,做出你想想要的布局 Grid与flex布局相似,将整个Grid分为了容器与子项(格子) Grid容器的三个重要的概念: 行和列单元格网…

webform里的验证控件
1.非空验证控件:RequireFieldValidator ;2.数据比较验证:CompareValidator ;3.数据范围验证:RangeValidator ;4.正则表达式验证:RegularExpressionValidator ;5.自定义条件验证&…

hash是线程安全的吗?怎么解决?_这次进程、线程、多线程和线程安全问题,一次性帮你全解决了...
1. 什么是进程一个软件,在操作系统中运行时,我们称其为进程。进程是操作系统分配资源的最小单元,线程是操作系统调度的最小单元。2. 什么是线程在一个进程中,每个独立的功能都需要独立的去运行,这时又需要把当前这个进…

WinXP不能共享Win7的打印机的解决方法
现在很多企业里存在着WinXP和Win7混用,WinXP不能正常共享Win7的文件和打印机,经过设置发现Win7可以Ping通Winxp并且也可以发现WinXP的共享文件,可是WinXP却不能共享Win7的文件和打印机,看了一下相关资料后简单设置就解决了这个问题…

第三阶段 10_JavaWeb基础_
因为要准备接本,不一定能够每天更新 转载于:https://www.cnblogs.com/BaiZe258/p/9251075.html

工厂模式(Factory)(转)
先来明确一个问题,那就是有的时候,实例化这个活动不应该总是公开的进行, 也就是不要公开的使用 new 操作符,因为,这样容易造成耦合问题。 我们不应该针对实现编程,但是当我们在使用 new 的时候,…

Asp.net后台创建HTML
为了使HTML界面中的内容能根据数据库中的内容动态显示用户需要的内容,或者根据权限不同要显示同而实现页面内容的动态创建 使用HtmlGenericControl创建HTML标签 引入命名空间: using System.Web.UI.HtmlControls; 更改其属性: hgg_div.Attributes.Add("style&q…

oracle视图(转)
视图的概念 视图是基于一张表或多张表或另外一个视图的逻辑表。视图不同于表,视图本身不包含任何数据。表是实际独立存在的实体,是用于存储数据的基本结构。而视图只是一种定义,对应一个查询语句。视图的数据都来自于某些表,这些…

Redis 事物
redis 事物: Redis 事物的实现: 首先 wath监控键值 myKey开启批量执行 multi,执行命令入列,执行 exec 。如果监控的键值mykey 没有被修改过,则exec 中批量执行的命令成功,否则执行失败。无论执行成功与否&a…
python dos攻击_利用SMB漏洞DoS攻击任何Windows系统
原标题:利用SMB漏洞DoS攻击任何Windows系统近日微软报出SMB V1存在漏洞,安全研究员并将此漏洞称作 “ SMBLoris ”,解释其能够发动拒绝服务(Dos)攻击,可以感染 Windows 2000 及以上操作系统的任一版本 SMB …

java基础编程题(2)
1、给定一个二叉树,找出其最大深度。 注:二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x…

python元组转字典_python中怎么将元组、字典转化为列表
python中将元组、字典转化为列表的方法: python中可以使用list()方法将元组或字典转化为列表: list()方法语法:list( tup ) 参数 tup -- 要转换为列表的元组。 返回值 返回列表。 示例: 将元组转换为列表:#!/usr/bin/p…

搭建Git服务器教程转载
1. 在Windows下使用sshmsysgit客户端搭建Git服务器 http://www.codeproject.com/Articles/296398/Step-by-Step-Setup-Git-Server-on-Windows-with-CopS 2. 在Windows下使用Apachemsysgit客户端搭建Git服务器 http://www.devbean.info/2011/10/apache-git-server-on-windows/ 3…

存储过程处理错误数据
create or replace procedure ERR_REDUCEDATA is --sx --定义变量 v_realindiobjid VARCHAR2(100); v_indiobjid VARCHAR2(32); v_residuemoney number ; v_reducemoney number ; v_approbjid VARCHAR2(32); -- v_indiecoid VARCHAR2(32); --v_indiecocode VARCHAR2(32); v_Ap…
[置顶] 面向业务开发应用
自从计算机出现后,快速便捷的从太平洋一样的文海中找到水滴大小的资料真正成为了可能,而能够帮助人们实现这一愿望的程序员就像中世纪的航海家一样用神秘的代码程序指引着计算机一步一步实现的需求。而他们所用的被称之为“程序”的序列组合,…

vector方法
借鉴网上资料,整理了vector使用的一些方法,记录下来,方便以后查阅 vector初始化 vector<int>a(10) //只定义长度 vector<int>a(10,1)//长度为10,初始值为1 vector<int>a(b); //用b向量来创建a向量,…