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实现的登录和操作开心网脚本分享
Jul 09 Python
跟老齐学Python之玩转字符串(1)
Sep 14 Python
python 转换 Javascript %u 字符串为python unicode的代码
Sep 06 Python
Python tkinter实现的图片移动碰撞动画效果【附源码下载】
Jan 04 Python
python爬取网易云音乐评论
Nov 16 Python
PyQt5的安装配置过程,将ui文件转为py文件后显示窗口的实例
Jun 19 Python
python利用wx实现界面按钮和按钮监听和字体改变的方法
Jul 17 Python
使用 Django Highcharts 实现数据可视化过程解析
Jul 31 Python
在Django中实现添加user到group并查看
Nov 18 Python
利用Python的sympy包求解一元三次方程示例
Nov 22 Python
django列表筛选功能的实现代码
Mar 27 Python
Python实现照片卡通化
Dec 06 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
建立文件交换功能的脚本(二)
2006/10/09 PHP
thinkphp浏览历史功能实现方法
2014/10/29 PHP
PHP缓存工具XCache安装与使用方法详解
2018/04/09 PHP
PHP四种排序算法实现及效率分析【冒泡排序,插入排序,选择排序和快速排序】
2018/04/27 PHP
laravel 查询数据库获取结果实现判断是否为空
2019/10/24 PHP
js特殊字符过滤的示例代码
2014/03/05 Javascript
谈谈JSON对象和字符串之间的相互转换JSON.stringify(obj)和JSON.parse(string)
2015/10/01 Javascript
关于事件mouseover ,mouseout ,mouseenter,mouseleave的区别
2015/10/12 Javascript
详解AngularJS 模态对话框
2016/04/07 Javascript
浅谈js中几种实用的跨域方法原理详解
2016/12/02 Javascript
AngularJS入门教程二:在路由中传递参数的方法分析
2017/05/27 Javascript
关于Angular2 + node接口调试的解决方案
2017/05/28 Javascript
Vue如何实现组件的源码解析
2017/06/08 Javascript
Nodejs监听日志文件的变化的过程解析
2019/08/04 NodeJs
微信小程序云函数使用mysql数据库过程详解
2019/08/07 Javascript
[01:09]2014DOTA2国际邀请赛 TI4西雅图DOTA2 中国美女coser加油助威
2014/07/20 DOTA
一步步解析Python斗牛游戏的概率
2016/02/12 Python
详解Python pygame安装过程笔记
2017/06/05 Python
如何在sae中设置django,让sae的工作环境跟本地python环境一致
2017/11/21 Python
python+numpy+matplotalib实现梯度下降法
2018/08/31 Python
Python读取系统文件夹内所有文件并统计数量的方法
2018/10/23 Python
Python面向对象之类的内置attr属性示例
2018/12/14 Python
pycharm修改界面主题颜色的方法
2019/01/17 Python
对python中类的继承与方法重写介绍
2019/01/20 Python
在python image 中安装中文字体的实现方法
2019/08/22 Python
Allsole美国/加拿大:英国一家专门出售品牌鞋子的网站
2018/10/21 全球购物
外贸公司实习自我鉴定
2013/09/24 职场文书
文史专业毕业生自荐信
2013/11/17 职场文书
重阳节活动总结
2014/08/27 职场文书
国家税务局干部作风整顿整改措施
2014/09/18 职场文书
2014教师评职称工作总结
2014/11/10 职场文书
2014年电话销售工作总结
2014/12/01 职场文书
2015年中个人总结范文
2015/03/10 职场文书
小英雄雨来观后感
2015/06/09 职场文书
如何计划开一家便利店?
2019/07/31 职场文书
MySQL 开窗函数
2022/02/15 MySQL