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中的递归函数
Apr 27 Python
Python生成任意范围任意精度的随机数方法
Apr 09 Python
Pycharm 设置自定义背景颜色的图文教程
May 23 Python
python实现俄罗斯方块游戏
Mar 25 Python
python 函数的缺省参数使用注意事项分析
Sep 17 Python
python系统指定文件的查找只输出目录下所有文件及文件夹
Jan 19 Python
Python动态强类型解释型语言原理解析
Mar 25 Python
Python动态导入模块:__import__、importlib、动态导入的使用场景实例分析
Mar 30 Python
基于Python快速处理PDF表格数据
Jun 03 Python
python基于win32api实现键盘输入
Dec 09 Python
通过python-pptx模块操作ppt文件的方法
Dec 26 Python
Python集合set()使用的方法详解
Mar 18 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 socke 向指定页面提交数据
2008/07/23 PHP
PHP中的reflection反射机制测试例子
2014/08/05 PHP
PHP遍历目录文件的常用方法小结
2017/02/03 PHP
thinkphp中U方法按路由规则生成url的方法
2018/03/12 PHP
Yii框架Session与Cookie使用方法示例
2019/10/14 PHP
laravel 出现command not found问题的解决方案
2019/10/23 PHP
详解Javascript 装载和执行
2014/11/17 Javascript
javascript实现瀑布流自适应遇到的问题及解决方案
2015/01/28 Javascript
使用C++为node.js写扩展模块
2015/04/22 Javascript
js立即执行函数: (function ( ){})( ) 与 (function ( ){}( )) 有什么区别?
2015/11/18 Javascript
JavaScript基本语法学习教程
2016/01/14 Javascript
新入门node.js必须要知道的概念(必看篇)
2016/08/10 Javascript
jQuery动态生成Bootstrap表格
2016/11/01 Javascript
原生JS京东轮播图代码
2017/03/22 Javascript
javaScript 逻辑运算符使用技巧整理
2017/05/03 Javascript
jQuery+CSS实现的table表格行列转置功能示例
2018/01/08 jQuery
Koa2微信公众号开发之消息管理
2018/05/16 Javascript
JS选取DOM元素常见操作方法实例分析
2018/12/10 Javascript
JavaScript实现的鼠标跟随特效示例【2则实例】
2018/12/22 Javascript
JavaScript对象的特性与实践应用深入详解
2018/12/30 Javascript
微信小程序登录对接Django后端实现JWT方式验证登录详解
2019/07/29 Javascript
[04:03][TI9趣味短片] 小鸽子茶话会
2019/08/20 DOTA
在Python的Django框架中调用方法和处理无效变量
2015/07/15 Python
Python中函数eval和ast.literal_eval的区别详解
2017/08/10 Python
Python决策树分类算法学习
2017/12/22 Python
Python hashlib模块用法实例分析
2018/06/12 Python
Python Scapy随心所欲研究TCP协议栈
2018/11/20 Python
Python判断远程服务器上Excel文件是否被人打开的方法
2020/07/13 Python
文案策划求职信
2014/04/14 职场文书
岗位明星事迹材料
2014/05/18 职场文书
公司贷款承诺书
2014/05/30 职场文书
机电一体化毕业生自荐信
2014/06/19 职场文书
拾金不昧表扬稿大全
2015/05/05 职场文书
Python批量将csv文件转化成xml文件的实例
2021/05/10 Python
SpringBoot 集成短信和邮件 以阿里云短信服务为例
2022/04/22 Java/Android
html,css,javascript是怎样变成页面的
2023/05/07 HTML / CSS