Python中尝试多线程编程的一个简明例子


Posted in Python onApril 07, 2015

综述
    多线程是程序设计中的一个重要方面,尤其是在服务器Deamon程序方面。无论何种系统,线程调度的开销都比传统的进程要快得多。
  Python可以方便地支持多线程。可以快速创建线程、互斥锁、信号量等等元素,支持线程读写同步互斥。美中不足的是,Python的运行在Python 虚拟机上,创建的多线程可能是虚拟的线程,需要由Python虚拟机来轮询调度,这大大降低了Python多线程的可用性。希望高版本的Python可以 解决这个问题,发挥多CPU的最大效率。
  网上有些朋友说要获得真正多CPU的好处,有两种方法:
  1.可以创建多个进程而不是线程,进程数和cpu一样多。
  2.使用Jython 或 IronPython,可以得到真正的多线程。
  闲话少说,下面看看Python如何建立线程
  Python线程创建
  使用threading模块的 Thread类
  类接口如下

class  Thread( group=None, target=None, name=None, args=(), kwargs={})

 需要关注的参数是target和args. target 是需要子线程运行的目标函数,args是函数的参数,以tuple的形式传递。
  以下代码创建一个指向函数worker 的子线程
def worker(a_tid,a_account): 

     ... 

th = threading.Thread(target=worker,args=(i,acc) ) ;

启动这个线程

th.start()

等待线程返回
threading.Thread.join(th)

或者th.join()
如果你可以对要处理的数据进行很好的划分,而且线程之间无须通信,那么你可以使用:创建=》运行=》回收的方式编写你的多线程程序。但是如果线程之间需要访问共同的对象,则需要引入互斥锁或者信号量对资源进行互斥访问。
 下面讲讲如何创建互斥锁
创建锁
g_mutex = threading.Lock() 

  ....

使用锁 
    
for  ... : 

        #锁定,从下一句代码到释放前互斥访问 

        g_mutex.acquire() 

        a_account.deposite(1) 

        #释放 

        g_mutex.release()

最后,模拟一个公交地铁IC卡缴车费的多线程程序
  有10个读卡器,每个读卡器收费器每次扣除用户一块钱进入总账中,每读卡器每天一共被刷10000000次。账户原有100块。所以最后的总账应该为10000100。先不使用互斥锁来进行锁定(注释掉了锁定代码),看看后果如何。
import time,datetime
import threading
 
def worker(a_tid,a_account):
 global g_mutex
 print("Str " , a_tid, datetime.datetime.now() )
 for i in range(1000000):
  #g_mutex.acquire()
  a_account.deposite(1)
  #g_mutex.release()
 print("End " , a_tid , datetime.datetime.now() )
  
class Account:
 def __init__ (self, a_base ):
  self.m_amount=a_base
 def deposite(self,a_amount):
  self.m_amount+=a_amount
 def withdraw(self,a_amount):
  self.m_amount-=a_amount 
 
if __name__ == "__main__":
 global g_mutex
 count = 0
 dstart = datetime.datetime.now()
 print("Main Thread Start At: ", dstart)
 #init thread_pool
 thread_pool = []
 #init mutex
 g_mutex = threading.Lock()
 # init thread items
 acc = Account(100)
 for i in range(10):
  th = threading.Thread(target=worker,args=(i,acc) ) ;
  thread_pool.append(th)
   
 # start threads one by one  
 for i in range(10):
  thread_pool[i].start()
  
 #collect all threads
 for i in range(10):
  threading.Thread.join(thread_pool[i])
 dend = datetime.datetime.now()
 print("count=", acc.m_amount)
 print("Main Thread End at: ", dend, " time span ", dend-dstart)

注意,先不用互斥锁进行临界段访问控制,运行结果如下:
Python中尝试多线程编程的一个简明例子

从结果看到,程序确实是多线程运行的。但是由于没有对对象Account进行互斥访问,所以结果是错误的,只有3434612,比原预计少了很多。

打开锁后:
Python中尝试多线程编程的一个简明例子

这次可以看到,结果正确了。运行时间比不进行互斥多了很多,不过这也是同步的代价。
同时发现,写多线程,多进程类的程序,不能用自带的idle来运行。会有错误。

Python 相关文章推荐
python中enumerate函数用法实例分析
May 20 Python
Python中if __name__ == '__main__'作用解析
Jun 29 Python
彻底搞懂Python字符编码
Jan 23 Python
解决Python2.7读写文件中的中文乱码问题
Apr 12 Python
Python列表切片操作实例总结
Feb 19 Python
python 将有序数组转换为二叉树的方法
Mar 26 Python
pyqt 实现为长内容添加滑轮 scrollArea
Jun 19 Python
解决Jupyter因卸载重装导致的问题修复
Apr 10 Python
Python HTMLTestRunner如何下载生成报告
Sep 04 Python
Python文件操作及内置函数flush原理解析
Oct 13 Python
Django实现在线无水印抖音视频下载(附源码及地址)
May 06 Python
解决pytorch读取自制数据集出现过的问题
May 31 Python
Python的Flask框架中Flask-Admin库的简单入门指引
Apr 07 #Python
用Python实现一个简单的线程池
Apr 07 #Python
浅谈Python程序与C++程序的联合使用
Apr 07 #Python
浅要分析Python程序与C程序的结合使用
Apr 07 #Python
python实现根据用户输入从电影网站获取影片信息的方法
Apr 07 #Python
python中列表元素连接方法join用法实例
Apr 07 #Python
简单介绍Python中的filter和lambda函数的使用
Apr 07 #Python
You might like
php实现图片等比例缩放代码
2015/07/23 PHP
PHP对象相关知识总结
2017/04/09 PHP
Laravel + Elasticsearch 实现中文搜索的方法
2020/02/02 PHP
jQuery asp.net 用json格式返回自定义对象
2010/04/07 Javascript
node.js中的http.response.getHeader方法使用说明
2014/12/14 Javascript
触屏中的JavaScript事件分析
2015/02/06 Javascript
javascript用正则表达式过滤空格的实现代码
2016/06/14 Javascript
使用jquery获取url及url参数的简单实例
2016/06/14 Javascript
jquery实现超简单的瀑布流布局【推荐】
2017/03/08 Javascript
从零开始学习Node.js系列教程之SQLite3和MongoDB用法分析
2017/04/13 Javascript
vue中使用iview自定义验证关键词输入框问题及解决方法
2018/03/26 Javascript
.vue文件 加scoped 样式不起作用的解决方法
2018/05/28 Javascript
JavaScript实现的前端AES加密解密功能【基于CryptoJS】
2018/08/28 Javascript
详解Webpack-dev-server的proxy用法
2018/09/08 Javascript
微信小程序canvas.drawImage完全显示图片问题的解决
2018/11/30 Javascript
angular6根据environments配置文件更改开发所需要的环境的方法
2019/03/06 Javascript
详解微信小程序文件下载--视频和图片
2019/04/24 Javascript
微信小程序实现的canvas合成图片功能示例
2019/05/03 Javascript
js实现跳一跳小游戏
2020/07/31 Javascript
[02:02]特效爆炸!DOTA2珍宝之瓶待你开启
2018/08/21 DOTA
Python数据类型详解(二)列表
2016/05/08 Python
python数据清洗系列之字符串处理详解
2017/02/12 Python
python调用支付宝支付接口流程
2019/08/15 Python
PyCharm 2020.2 安装详细教程
2020/09/25 Python
Python测试框架:pytest学习笔记
2020/10/20 Python
俄罗斯优惠券网站:BIGLION
2017/05/21 全球购物
Ever New加拿大官网:彰显女性美
2018/10/05 全球购物
英国外籍人士的在线超市:British Corner Shop
2019/06/03 全球购物
自我评价如何写好?
2014/01/05 职场文书
预备党员学习十八届三中全会精神思想汇报
2014/09/13 职场文书
2014年敬老院工作总结
2014/12/08 职场文书
2015年学习部工作总结范文
2015/03/31 职场文书
人生哲理妙语30条:淡写流年,笑过人生
2019/09/04 职场文书
react中的DOM操作实现
2021/06/30 Javascript
Vue Mint UI mt-swipe的使用方式
2022/06/05 Vue.js
基于Python实现西西成语接龙小助手
2022/08/05 Golang