综述

 
多线程是程序设计中的一个重要方面,尤其是在服务器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;

 
注意,先不用互斥锁进行临界段访问控制,运行结果如下:
 
Main Thread Start At:     2009-01-13 00:17:55.296000
Str     0 2009-01-13 00:17:55.312000
Str     1 2009-01-13 00:17:55.453000
Str     2 2009-01-13 00:17:55.484000
Str     3 2009-01-13 00:17:55.531000
Str     4 2009-01-13 00:17:55.562000
Str     5 2009-01-13 00:17:55.609000
Str     6 2009-01-13 00:17:55.640000
Str     7 2009-01-13 00:17:55.687000
Str     8 2009-01-13 00:17:55.718000
Str     9 2009-01-13 00:17:55.781000
End     0 2009-01-13 00:18:06.250000
End     1 2009-01-13 00:18:07.500000
End     4 2009-01-13 00:18:07.531000
End     2 2009-01-13 00:18:07.562000
End     3 2009-01-13 00:18:07.593000
End     9 2009-01-13 00:18:07.609000
End     7 2009-01-13 00:18:07.640000
End     8 2009-01-13 00:18:07.671000
End     5 2009-01-13 00:18:07.687000
End     6 2009-01-13 00:18:07.718000
count= 3434612
Main Thread End at:     2009-01-13 00:18:07.718000     time span     0:00:12.422000
 
从结果看到,程序确实是多线程运行的。但是由于没有对对象Account进行互斥访问,所以结果是错误的,只有3434612,比原预计少了很多。
 
   把上面阴影部分代码的注释打开,运行结果如下
Main Thread Start At:     2009-01-13 00:26:12.156000
Str     0 2009-01-13 00:26:12.156000
Str     1 2009-01-13 00:26:12.390000
Str     2 2009-01-13 00:26:12.437000
Str     3 2009-01-13 00:26:12.468000
Str     4 2009-01-13 00:26:12.515000
Str     5 2009-01-13 00:26:12.562000
Str     6 2009-01-13 00:26:12.593000
Str     7 2009-01-13 00:26:12.640000
Str     8 2009-01-13 00:26:12.671000
Str     9 2009-01-13 00:26:12.718000
End     0 2009-01-13 00:27:01.781000
End     1 2009-01-13 00:27:05.890000
End     5 2009-01-13 00:27:06.046000
End     7 2009-01-13 00:27:06.078000
End     4 2009-01-13 00:27:06.109000
End     2 2009-01-13 00:27:06.140000
End     6 2009-01-13 00:27:06.156000
End     8 2009-01-13 00:27:06.187000
End     3 2009-01-13 00:27:06.203000
End     9 2009-01-13 00:27:06.234000
count= 10000100
Main Thread End at:     2009-01-13 00:27:06.234000     time span     0:00:54.078000
 
这次可以看到,结果正确了。运行时间比不进行互斥多了很多,需要花54秒才能运行(我机器烂,没钱更新,呵呵),不过这也是同步的代价,没办法。

Python多线程 简明例子的更多相关文章

  1. python多线程简单例子

    python多线程简单例子 作者:vpoet mail:vpoet_sir@163.com import thread def childthread(threadid): print "I ...

  2. python两段多线程的例子

    记录瞬间 =====================其一===================== # coding:UTF-8 import os import threading from tim ...

  3. Python 多线程教程:并发与并行

    转载于: https://my.oschina.net/leejun2005/blog/398826 在批评Python的讨论中,常常说起Python多线程是多么的难用.还有人对 global int ...

  4. python 多线程就这么简单(转)

    多线程和多进程是什么自行google补脑 对于python 多线程的理解,我花了很长时间,搜索的大部份文章都不够通俗易懂.所以,这里力图用简单的例子,让你对多线程有个初步的认识. 单线程 在好些年前的 ...

  5. python 多线程就这么简单(续)

    之前讲了多线程的一篇博客,感觉讲的意犹未尽,其实,多线程非常有意思.因为我们在使用电脑的过程中无时无刻都在多进程和多线程.我们可以接着之前的例子继续讲.请先看我的上一篇博客. python 多线程就这 ...

  6. 【跟我一起学Python吧】Python 多线程

    其实自我感觉Python的多线程很类似于Java的多线程机制,但是比JAVA的多线程更灵活.在早期的Python多线程实现中,采用了thread模块.例如: from time import ctim ...

  7. Python多线程锁

    [Python之旅]第六篇(四):Python多线程锁   python lock 多线程 多线程使用方法 多线程锁 摘要:   在多线程程序执行过程中,为什么需要给一些线程加锁以及如何加锁,下面就来 ...

  8. Day9 - Python 多线程、进程

    Python之路,Day9, 进程.线程.协程篇   本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线 ...

  9. Python 绝对简明手册

    Python 绝对简明手册 help(函数名)来获取相关信息 另外,自带的文档和google也是不可少的 2. 基本语法2.1. if / elif / else x=int(raw_input(&q ...

随机推荐

  1. FZU 1650 1752 a^b mod c

    http://acm.fzu.edu.cn/problem.php?pid=1752 http://acm.fzu.edu.cn/problem.php?pid=1650 给跪了. 我的快速幂会越界. ...

  2. BZOJ 1695 [Usaco2007 Demo]Walk the Talk 链表+数学

    题意:链接 方法:乱搞 解析: 出这道题的人存心报复社会. 首先这个单词表-先上网上找这个单词表- 反正总共2265个单词.然后就考虑怎么做即可了. 刚開始我没看表,找不到怎么做,最快的方法我也仅仅是 ...

  3. 事件处理之二:点击事件监听器的五种写法 分类: H1_ANDROID 2013-09-11 10:32 4262人阅读 评论(1) 收藏

    首选方法二! 方法一:写一个内部类,在类中实现点击事件 1.在父类中调用点击事件 bt_dail.setOnClickListener(new MyButtonListener()); 2.创建内部类 ...

  4. php array数组的相关处理函数and str字符串处理与正则表达式

    下面给各位同学整理了一些关于php array数组的相关处理函数and str字符串处理与正则表达式,希望文章对你会有所帮助.   数组的相关处理函数: 1)数组的键值操作函数 array_value ...

  5. ubuntu里面设置颜色

    比方我是这么写的:base_color:#FAF9DE;selected_bg_color:#008522 (背景为浅黄色,选择框为绿色) 写完之后按回车确认,立即生效! 这里另一个极其严重的 bug ...

  6. 文本处理之可视化wordcloud

    什么是词云 词云又叫文字云,是对文本数据中出现频率较高的“关键词”在视觉上的突出呈现,形成关键词的渲染形成类似云一样的彩色图片,从而一眼就可以领略文本数据的主要表达意思. 准备工作: python开发 ...

  7. zxing的使用及优化

    二维码介绍 zxing项目是谷歌推出的用来识别多种格式条形码的开源项目,项目地址为https://github.com/zxing/zxing,zxing有多个人在维护,覆盖主流编程语言,也是目前还在 ...

  8. 【b094&&z14】靶形数独

    [问题描述] 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的分们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向Z博士请教,Z博士拿出了他最近发明的&qu ...

  9. NOIP模拟 cube - 数学

    题目原文: 豆豆还是觉得自己智商太低了,就又去做数学题了.一看到题,他就觉得自己可能真的一点智商都没有.便哭着跑来像 dalao 求教:如果存在正整数 A,B ,满足 A3 - B3 = x ,则称质 ...

  10. HDU 1244 Max Sum Plus Plus Plus - dp

    传送门 题目大意: 给一个序列,要求将序列分成m段,从左至右每一段分别长l1,l2,...lm,求最大的和是多少. 题目分析: 和最大m段子段和相似,先枚举\(i \in [1,m]\),然后$j \ ...