python学习笔记- 多线程(1)
学习多线程首先先要理解线程和进程的关系。
进程
计算机的程序是储存在磁盘中的可执行的二进制文件,执行时把这些二进制文件加载到内存中,操作系统调用并交给处理器执行对应操作,进程是程序的一次执行过程,这是一个动态的概念程序本没有生命的实体,只有通过处理器才能赋予程序生命。进程最大的特点就是可以申请和拥有系统资源,这是一个动态的概念,是一个活动的实体(比如qq程序需要的内存空间等等),进程不止是程序代码,还包括当前的活动,通过程序计数器的值和处理寄存器的内容来表示。
而线程是进程的一部分,一个进程可以包含多个线程在运行,线程拥有的资源是进程聪操作系统申请并拥有的资源,在引入进程的操作系统通常是把该线程所属的进程作为线程分配资源的基本单位,从而线程基本不拥有系统资源。
那么可想而知线程和进程的最大区别就是子进程和父线程拥有不同的代码和数据空间,而进程中的多个线程资源是共享的,所以进程的上下文切换要比进程快得多。多线程主要是为了节约cpu运行的时间。
总而言之进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
单线程
单线程的运行是顺序运行的,比如同时执行两个不嵌套的循环,第一个执行完第二个循环才能执行,程序执行时间基本为两个循环的总时间
这个程序一共耗时8s。
我用的是python 2.7,Ubuntu自带2.7
python封装了两个类库从而对多线程的支持:thread和threading.thread是比较低级别的、原始的线程以及一个简单的锁。threading提供了Rlock和Condition(下文会详细介绍)
thread模块
thread模块提供了start_new_thread(function,args,kwargs)方法来开启一个新线程 ,由于前两个参数是必需的,所以第二个参数为空也必需传一个空的元祖,函数申明如下图:
这个程序执行的时间是所有同时执行的线程的最长的进程时间6s,即主线程的6s。那么为什么要让主线程sleep6s呢?那是因为我们知道开启的两个子线程都是4s,让主线程休眠6s刚好可以等到子线程执行完毕,如果没有sleep 6s这句代码,那么主线程会直接往下执行,直至主线程结束,那么会导致子线程还没有执行完毕也随着主线程的结束而结束,而且主线程休眠6s,而子线程4s就执行完毕,那么这样主线程晚退出了2s。
上面是我们人为手动让主线程休眠6s,可能会导致主线程过早或过晚的退出,那么如何去实现这个动态的过程。
上面使用了锁实现了这一需求。
threading模块
上面已经可以很清楚的看出thread模块的局限,当主线程退出时,所有的子线程无论是否已经执行完毕都要被强行退出,于是就有了守护线程的概念,threading模块则支持守护线程。
调用threading模块的threading.Thread(fun,agr)的工厂方法生成实例。在调用start方法开启线程,在对每个线程调用join方法。join方法会让这个主线程等待子线程的终止或者达到在给了timeout参数线程执行超时结束,不然主线程不会结束退出。
使用多线程实现数据同步
使用多线程时很容易出现下面的问题。
假设两个线程对象t1和t2都要对num=0进行增1运算,t1和t2都各对num修改10次,num的最终的结果应该为20。但是由于是多线程访问,有可能出现下面情况:在num=0时,t1取得num=0。系统此时把t1调度为”sleeping”状态,把t2转换为”running”状态,t2页获得num=0。然后t2对得到的值进行加1并赋给num,使得num=1。然后系统又把t2调度为”sleeping”,把t1转为”running”。线程t1又把它之前得到的0加1后赋值给num。这样,明明t1和t2都完成了1次加1工作,但结果仍然是num=1。
上面的case描述了多线程情况下最常见的问题之一:数据共享。当多个线程都要去修改某一个共享数据的时候,我们需要对数据访问进行同步。
最简单的同步机制就是“锁”。锁对象由threading.RLock类创建。线程可以使用锁的acquire()方法获得锁,这样锁就进入“locked”状态。每次只有一个线程可以获得锁。如果当另一个线程试图获得这个锁的时候,就会被系统变为“blocked”状态,直到那个拥有锁的线程调用锁的release()方法来释放锁,这样锁就会进入“unlocked”状态。“blocked”状态的线程就会收到一个通知,并有权利获得锁。如果多个线程处于“blocked”状态,所有线程都会先解除“blocked”状态,然后系统选择一个线程来获得锁,其他的线程继续沉默(“blocked”)。
Python中的thread模块和Lock对象是Python提供的低级线程控制工具,使用起来非常简单。如下例所示:
import thread
import time
mylock = thread.allocate_lock() #Allocate a lock
num=0 #Shared resource def add_num(name):
global num
while True:
mylock.acquire() #Get the lock
# Do something to the shared resource
print 'Thread %s locked! num=%s'%(name,str(num))
if num >= 5:
print 'Thread %s released! num=%s'%(name,str(num))
mylock.release()
thread.exit_thread()
num+=1
print 'Thread %s released! num=%s'%(name,str(num))
mylock.release() #Release the lock. def test():
thread.start_new_thread(add_num, ('A',))
thread.start_new_thread(add_num, ('B',)) if __name__== '__main__':
test()
如上就简单的实现各个线程的数据共享。
python学习笔记- 多线程(1)的更多相关文章
- OpenCV之Python学习笔记
OpenCV之Python学习笔记 直都在用Python+OpenCV做一些算法的原型.本来想留下发布一些文章的,可是整理一下就有点无奈了,都是写零散不成系统的小片段.现在看 到一本国外的新书< ...
- Python学习笔记进阶篇——总览
Python学习笔记——进阶篇[第八周]———进程.线程.协程篇(Socket编程进阶&多线程.多进程) Python学习笔记——进阶篇[第八周]———进程.线程.协程篇(异常处理) Pyth ...
- 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁
什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...
- Java学习笔记-多线程-创建线程的方式
创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...
- python学习笔记整理——字典
python学习笔记整理 数据结构--字典 无序的 {键:值} 对集合 用于查询的方法 len(d) Return the number of items in the dictionary d. 返 ...
- VS2013中Python学习笔记[Django Web的第一个网页]
前言 前面我简单介绍了Python的Hello World.看到有人问我搞搞Python的Web,一时兴起,就来试试看. 第一篇 VS2013中Python学习笔记[环境搭建] 简单介绍Python环 ...
- python学习笔记之module && package
个人总结: import module,module就是文件名,导入那个python文件 import package,package就是一个文件夹,导入的文件夹下有一个__init__.py的文件, ...
- python学习笔记(六)文件夹遍历,异常处理
python学习笔记(六) 文件夹遍历 1.递归遍历 import os allfile = [] def dirList(path): filelist = os.listdir(path) for ...
- python学习笔记--Django入门四 管理站点--二
接上一节 python学习笔记--Django入门四 管理站点 设置字段可选 编辑Book模块在email字段上加上blank=True,指定email字段为可选,代码如下: class Autho ...
随机推荐
- Lind.DDD.Aspects通过Plugins实现方法的动态拦截~Lind里的AOP
回到目录 .Net MVC之所以发展的如些之好,一个很重要原因就是它公开了一组AOP的过滤器,即使用这些过滤器可以方便的拦截controller里的action,并注入我们自己的代码逻辑,向全局的异常 ...
- background例子
- nexus 社区版3.0.2部署、访问
下载nexus社区办(oss): https://www.sonatype.com/download-oss-sonatype 目前最新版本 nexus-3.0.2-02-win64.zip nex ...
- Oozie分布式任务的工作流——Spark篇
Spark是现在应用最广泛的分布式计算框架,oozie支持在它的调度中执行spark.在我的日常工作中,一部分工作就是基于oozie维护好每天的spark离线任务,合理的设计工作流并分配适合的参数对于 ...
- Linux设备管理(一)_kobject, kset,ktype分析
Linux内核大量使用面向对象的设计思想,通过追踪源码,我们甚至可以使用面向对象语言常用的UML类图来分析Linux设备管理的"类"之间的关系.这里以4.8.5内核为例从kobje ...
- 第10章 Shell编程(4)_流程控制
5. 流程控制 5.1 if语句 (1)格式: 格式1 格式2 多分支if if [ 条件判断式 ];then #程序 else #程序 fi if [ 条件判断式 ] then #程序 else # ...
- 亡命之徒aaaaaa.......chao
前端是一个看似入门门槛不高,但要学好很难的领域.前端的知识体系庞杂又松散,技术演进快,如果摸不清脉络的话很容易陷入盲人摸象的困境甚至跑偏.其实只要掌握了正确的方法,学习前端和学好前端就只是个时间问题. ...
- ASP.NET Aries 4.0 开源发布:已完成基础功能优化重写
主要更新: 1:增加AR.Global.GetUser() 方法返回当前登陆者的用户信息. 2:重写AR.Combobox 支持下拉树. 3:调整及扩展Input下拉的配置参数. 4:优化及新增AR. ...
- 【腾讯Bugly干货分享】微信热补丁Tinker的实践演进之路
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57ad7a70eaed47bb2699e68e Dev Club 是一个交流移动 ...
- K-近邻算法(KNN)
简介 k近邻算法是数据分类一种常用的算法,属于监督学习算法的一类,它采用不同特征值之的距离进行分类.K近邻算法具有精度高.对异常值不敏感.无数据输入假定的优点,缺点是计算复杂度高.空间复杂度高.适用于 ...