python技术简介_Python多线程技术简介,简单,阐述,python
python多线程
python中创建多线程方法有两种,这里只介绍简单的一种:
from threading import Thread #导入模块
import time
def test(thread_num): #线程需要执行的函数
print('线程%d:aaaaaaa' % thread_num)
time.sleep(2)
print('线程%d:bbbbbbb' % thread_num )
time.sleep(2)
print('线程%d:ccccccc' % thread_num)
if __name__ == '__main__':
print('主线程开启...')
#创建线程,target表示线程需要执行的函数,args表示函数的参数,必须是元组形式
t1 = Thread(target=test, args=(1,))
t2 = Thread(target=test, args=(2,))
t1.start() #线程t1就绪
t2.start() #线程t2就绪
t1.join()#主线程等待线程t1结束
t2.join() #主线程等待线程t2结束
print('主线程结束...')
这是运行两次的结果:
执行
start
方法后,表明线程以准备就绪,但还没开始执行,具体什么时间执行由cpu决定。
可以看到,打印
ccccccc
的时候,第一次是线程2先执行,第二次是线程1先执行,实际上这是随机的,是由操作系统自己决定哪个线程先执行的。
线程锁
当多个线程同时对某个数据进行修改的时候,就会导致数据结果与预期不符,例如,
from threading import Thread
money = 0
def change_money(n=300000):
global money
for i in range(n): #进行30万次 +1 操作
money += 1
t1 = Thread(target=change_money, args=())
t2 = Thread(target=change_money, args=())
if __name == '__main__':
t1.start()
t2.start()
t1.join()
t2.join()
print('money:',money)
该程序即是对
money
全局变量进行30万次 +1 操作,由于是有2个线程,按道理总共是操作了60万次,因此结果应该是
600000
,但是,运行3次的输出却是:
明显与预期不符,为什么会这样,因为
money += 1
这条语句在程序执行起来实际上是有2步操作的,第一步是
计算
money + 1
,第二步是把计算的结果
赋值
给变量
money
。
然而,当我们开启了多个线程后,可能某个线程只执行了第一步,还未执行第二步,数据就被另一个线程拿去使用了。如果这些线程执行的次数很少,可能不会出问题,但是执行几十万、几百万次这种操作时,就会出现这样的状况。
因此为了避免这种状况发生,可以给数据上锁,将数据锁起来,由于锁只有一个,某个线程获得了锁后,另一个线程就必须等待这个线程把锁释放,然后所有线程公平竞争获取这个锁。线程获得锁后,在释放锁前把计算和赋值这两步操作都执行了,这样就不会出错了。
例如:
from threading import Thread, Lock
money = 0
def change_money(n=500000):
global money
for i in range(n):
lock.acquire() #获得锁
money += 1
lock.release() #操作完成,释放锁
t1 = Thread(target=change_money, args=())
t2 = Thread(target=change_money, args=())
lock = Lock() #首先创建锁
t1.start()
t2.start()
t1.join()
t2.join()
print('money:',money)
这是运行3次的结果:
可以看到,没有出错。
时间问题
假设对
money
执行 6 次 +1 操作,每操作一次等待 2 秒,最后共耗费多少时间?
在没学过线程之前,也就是执行时只采用一个线程,按道理最后耗时大概是
12秒
,实际上也是这样,此处不再写代码了,可以自己试一下。
学了多线程后,可以采用2个线程,每个线程操作 3 次,理论上耗时
6秒
,看下这个代码:
from threading import Thread, Lock
import time
money = 0
def change_money(n=3):
global money
for i in range(n):
lock.acquire()
money += 1
time.sleep(2) #等待2秒
lock.release()
t1 = Thread(target=change_money, args=())
t2 = Thread(target=change_money, args=())
lock = Lock()
time1 = time.time()
t1.start()
t2.start()
t1.join()
t2.join()
time2 = time.time()
print('money:',money)
print('耗时:{}'.format(time2 - time1))
输出耗时12秒,怎么回事,不急,再看下面这个代码(在上面这个代码基础上稍微改动一下):
from threading import Thread, Lock
import time
money = 0
def change_money(n=3):
global money
for i in range(n):
lock.acquire()
money += 1
lock.release()
time.sleep(2) #等待2秒
t1 = Thread(target=change_money, args=())
t2 = Thread(target=change_money, args=())
lock = Lock()
time1 = time.time()
t1.start()
t2.start()
t1.join()
t2.join()
time2 = time.time()
print('money:',money)
print('耗时:{}'.format(time2 - time1))
这时输出为
6秒
, 倒是跟理论值符合。比较这两个代码,只有 11和12行有改动,第一个是先等待2秒,再释放锁;第二个是先释放锁,再等待2秒,问题关键就在于这个锁。
因为锁只有一个,锁在释放前其他所有未获得锁的线程都会等待锁的释放,即锁在释放前只能有一个线程执行,而
time.sleep(2)
这句代码放在
lock.release()
前的时候,因为有2个线程,每个线程操作3次,因此耗时
2 * 3 * 2 = 12秒
;
但是当
lock.release()
这句代码放在
time.sleep(2)
前的时候,即先释放锁,再等待,由于释放了锁后,释放锁的线程在等待2秒,而另一个线程立即获取锁,然后进行计算操作,由于计算操作的时间很快,
可忽略不计
,最后就会出现2个线程都在
同时
(可以认为是同时)执行等待2秒这个操作,因此最后实际上只耗费了一个线程的时间
3 * 2 = 6秒
python技术简介_Python多线程技术简介,简单,阐述,python相关推荐
- python安装方法_Python基础入门——简介和环境配置,超实用!
作者 | kbsc13 来源 | 机器学习与计算机视觉(ID:AI_Developer) 上周结束了如何构造一个机器学习项目的系列文章,当然还有一篇简单的总结以及介绍一些入门的学习资料,不过还在整理, ...
- python多线程并发写入_Python多线程并发的简单测试
之前也写了一些简单的Python程序,对于多线程的并发一直没有涉及,今天决定先突破一下,把这个部分的内容先快速的掌握,然后在这个基础上细化改进. 我的好友冰川擅长Python技术,所以就拿来主义,参考 ...
- python数据类型介绍_python的数据类型简介
ipython:原生python不具有命令行补全等功能,这个工具提供了类似shell的功能,方便学习使用 安装: wget https://repo.continuum.io/archive/Anac ...
- python爬虫多进程_Python爬虫技术--基础篇--多进程
要让Python程序实现多进程(multiprocessing),我们先了解操作系统的相关知识. Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊.普通的函数调用,调用一次,返回 ...
- python的lxml库简介_Python lxml库简介
Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发. lxml是一个Python库,使用它可以轻松处理XML和HTML文件,还可以用于web爬取.市面上有很多现 ...
- python排队叫号_python多线程实现代码(模拟银行服务操作流程)
1.模拟银行服务完成程序代码 目前,在以银行营业大厅为代表的窗口行业中大量使用排队(叫号)系统,该系统完全模拟了人群排队全过程,通过取票进队.排队等待.叫号服务等功能,代替了人们站队的辛苦. 排队叫号 ...
- python线程唤醒_python 多线程
python 多线程 真正的多线程吗? 对于多核处理器,在同一时间确实可以多个线程独立运行,但在Python中确不是这样的了.原因在于,python虚拟机中引入了GIL这一概念.GIL(Global ...
- 理解python并发编程_Python并发编程很简单
上次已经和大家探讨了关于进程和线程的区别和联系相关的东东,今天呢,咱们再次回到 好啦,废话少说,咱们就开始吧! 首先说一下哦,_thread和threading哦,到这可能有朋友会问了,这两个有什么区 ...
- python线程数组_Python多线程
多线程技术需.要用到threading模块,应当避免使用thread模块,原因是它不支持守护线程.当主线程退出时,所有的子线程不管他们是都还在工作,都会被强制退出.有时候我们并不希望发生这种行为 ,这 ...
最新文章
- centos/Debian/Ubuntu下编译安装pypy
- 解决The server cannot be started because one or more of the ports are invalid.
- a partial surjection的题库
- Android Kotlin Coroutines ktx扩展
- jquery饼状图插件的指引线_JQuery图表插件Highcharts示例教程
- java中debug使用
- Linux下性能压测之系统参数调优
- 干货分享:单片机编程学习攻略!
- 【渝粤教育】国家开放大学2018年春季 8638-22T薪酬制度与薪酬管理 参考试题
- docker helowin 迁移_禅道在docker上部署与迁移
- MSSQL OPTION语句详解
- 精确选择识别png图片有像素的区域(使用方法)
- 用数据告诉你出租车资源配置是否合理
- 解决dephi使用Word时出现“没有注册接口”的情况。
- RS485芯片与单片机接口中的一个容易忽略的隐患
- python VTK画3D方框
- c语言二维指针类型转换,二维数组和指针(C语言)
- [WinError 6] 句柄无效。
- html5如何设置视频为静音,html5中设置或返回音频/视频是否应该被静音的属性muted-...
- python修改图片大小为30kb_Python的Tornado框架实现图片上传及图片大小修改