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相关推荐

  1. python安装方法_Python基础入门——简介和环境配置,超实用!

    作者 | kbsc13 来源 | 机器学习与计算机视觉(ID:AI_Developer) 上周结束了如何构造一个机器学习项目的系列文章,当然还有一篇简单的总结以及介绍一些入门的学习资料,不过还在整理, ...

  2. python多线程并发写入_Python多线程并发的简单测试

    之前也写了一些简单的Python程序,对于多线程的并发一直没有涉及,今天决定先突破一下,把这个部分的内容先快速的掌握,然后在这个基础上细化改进. 我的好友冰川擅长Python技术,所以就拿来主义,参考 ...

  3. python数据类型介绍_python的数据类型简介

    ipython:原生python不具有命令行补全等功能,这个工具提供了类似shell的功能,方便学习使用 安装: wget https://repo.continuum.io/archive/Anac ...

  4. python爬虫多进程_Python爬虫技术--基础篇--多进程

    要让Python程序实现多进程(multiprocessing),我们先了解操作系统的相关知识. Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊.普通的函数调用,调用一次,返回 ...

  5. python的lxml库简介_Python lxml库简介

    Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发. lxml是一个Python库,使用它可以轻松处理XML和HTML文件,还可以用于web爬取.市面上有很多现 ...

  6. python排队叫号_python多线程实现代码(模拟银行服务操作流程)

    1.模拟银行服务完成程序代码 目前,在以银行营业大厅为代表的窗口行业中大量使用排队(叫号)系统,该系统完全模拟了人群排队全过程,通过取票进队.排队等待.叫号服务等功能,代替了人们站队的辛苦. 排队叫号 ...

  7. python线程唤醒_python 多线程

    python 多线程 真正的多线程吗? 对于多核处理器,在同一时间确实可以多个线程独立运行,但在Python中确不是这样的了.原因在于,python虚拟机中引入了GIL这一概念.GIL(Global ...

  8. 理解python并发编程_Python并发编程很简单

    上次已经和大家探讨了关于进程和线程的区别和联系相关的东东,今天呢,咱们再次回到 好啦,废话少说,咱们就开始吧! 首先说一下哦,_thread和threading哦,到这可能有朋友会问了,这两个有什么区 ...

  9. python线程数组_Python多线程

    多线程技术需.要用到threading模块,应当避免使用thread模块,原因是它不支持守护线程.当主线程退出时,所有的子线程不管他们是都还在工作,都会被强制退出.有时候我们并不希望发生这种行为 ,这 ...

最新文章

  1. centos/Debian/Ubuntu下编译安装pypy
  2. 解决The server cannot be started because one or more of the ports are invalid.
  3. a partial surjection的题库
  4. Android Kotlin Coroutines ktx扩展
  5. jquery饼状图插件的指引线_JQuery图表插件Highcharts示例教程
  6. java中debug使用
  7. Linux下性能压测之系统参数调优
  8. 干货分享:单片机编程学习攻略!
  9. 【渝粤教育】国家开放大学2018年春季 8638-22T薪酬制度与薪酬管理 参考试题
  10. docker helowin 迁移_禅道在docker上部署与迁移
  11. MSSQL OPTION语句详解
  12. 精确选择识别png图片有像素的区域(使用方法)
  13. 用数据告诉你出租车资源配置是否合理
  14. 解决dephi使用Word时出现“没有注册接口”的情况。
  15. RS485芯片与单片机接口中的一个容易忽略的隐患
  16. python VTK画3D方框
  17. c语言二维指针类型转换,二维数组和指针(C语言)
  18. [WinError 6] 句柄无效。
  19. html5如何设置视频为静音,html5中设置或返回音频/视频是否应该被静音的属性muted-...
  20. python修改图片大小为30kb_Python的Tornado框架实现图片上传及图片大小修改

热门文章

  1. hdu 4288 Coder (成都赛区 线段树)
  2. JBPM中文乱码的一种解决方法
  3. 解决git rebase操作后推送远端分支不成功的问题
  4. 没业绩怎么写好年终总结?这样写总结年终奖翻倍!
  5. 0-1背包问题的简单解释
  6. 【复赛前排分享(二)】收好这份王牌优化指南,助你轻松上分无压力
  7. AdaPrompt:进一步将下游任务融入到预训练模型
  8. mysql安装了老版本_Windows 环境下 MySQL 5.7 安装配置指南
  9. 面试pythone_叮!你需要的Python面试指南以送到!
  10. 平台卖家要不要做独立站?