Python并发机制(二)——多线程
来源:互联网 发布:如何用网络电视连手机 编辑:程序博客网 时间:2024/05/21 09:32
Python并发机制(二)——多线程
实例化threading.Thread()
import threading,timedef fn(n): print n print str(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()))def main(): tpool = [] for i in range(10): t = threading.Thread(target=fn,args=(0,)) tpool.append(t) for t in tpool: t.start() for t in tpool: threading.Thread.join(t)if __main__ == '__name__': main()
运行结果如下:
1 12016-11-22 01:22:292016-11-22 01:22:29112016-11-22 01:22:292016-11-22 01:22:2912016-11-22 01:22:29 12016-11-22 01:22:2912016-11-22 01:22:291 12016-11-22 01:22:29 12016-11-22 01:22:292016-11-22 01:22:29
自定义线程类的实例化
import threading,timeclass myThread(threading.Thread): def __init__(self,n): threading.Thread.__init__(self) self.n = n def fn(self): print self.n print str(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())) def run(self): self.fn()def main(): tpool = [] for i in range(10): tpool.append(myThread(1)) for t in tpool: t.start() for t in tpool: t.join()if __name__ == '__main__': main()
运行结果如下:
12016-11-22 01:46:361 12016-11-22 01:46:362016-11-22 01:46:36 12016-11-22 01:46:361 12016-11-22 01:46:362016-11-22 01:46:3612016-11-22 01:46:3612016-11-22 01:46:3612016-11-22 01:46:36 12016-11-22 01:46:36
使用multiprocesssing.dummy执行多线程任务
#coding=utf-8import urllib2import timefrom multiprocesssing.dummy import Poolimport threadingfrom multiprocesssing import Pool as PPoolurls = [ 'http://www.python.org', 'http://www.python.org/about/', 'http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html', 'http://www.python.org/doc/', 'http://www.python.org/download/', 'http://www.python.org/getit/', 'http://www.python.org/community/', 'https://wiki.python.org/moin/', 'http://planet.python.org/', 'https://wiki.python.org/moin/LocalUserGroups', 'http://www.python.org/psf/', 'http://docs.python.org/devguide/', 'http://www.python.org', 'http://www.python.org/about/', 'http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html', 'http://www.python.org/doc/', 'http://www.python.org/download/', 'http://www.python.org/getit/', 'http://www.python.org/community/', 'https://wiki.python.org/moin/', 'http://planet.python.org/', 'https://wiki.python.org/moin/LocalUserGroups', 'http://www.python.org/psf/', 'http://docs.python.org/devguide/',]#单线程时间start = time.time()result = map(urllib2.urlopen,urls)t1 = time.time() - startprint "单线程时间:",t1#4线程时间time.sleep(1)start = time.time()pool = Pool(4)result = pool.map(urllib2.urlopen,urls)pool.close()pool.join()t4 = time.time() - startprint "4线程时间:",t4#8线程时间time.sleep(1)start = time.time()pool = Pool(12)result = pool.map(urllib2.urlopen,urls)pool.close()pool.join()t8 = time.time() - startprint "12线程时间:",t8#threading模块4线程time.sleep(1)start = time.time()t = []for i in range(4): t.append(threading.Thread(target=map,args=(urllib2.urlopen,urls[i*3:i*3+3])))for th in t: th.start()for th in t: th.join()t = time.time() - startprint "threading模块4线程:",t#4进程time.sleep(1)start = time.time()pool = PPool(processes=4)#注意加_async,非阻塞版本results = pool.map_async(urllib2.urlopen,urls)pool.close()pool.join()t = time.time() - startprint "4进程:",t
运行结果如下:
单线程时间: 23.56174492844线程时间: 5.8167810440112线程时间: 2.70931982994threading模块4线程: 4.121351957324进程: 5.78697896004
注意:受GIL机制(如下)影响的多线程实质上是交替单线程执行,利用multiproceessing. dummy.Pool实例化的线程池能实现并发,类似于进程池,如果将它们分为两类,则第一类更有利于IO密集型程序(如上例偏IO),第二类更有利于CPU密集型程序
python(CPython)全局锁(GIL)机制
首先需要明确的一点是 GIL 并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码。有名的编译器例如GCC,INTEL C++,Visual C++等。Python也一样,同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行环境来执行。像其中的JPython就没有GIL。然而因为CPython是大部分环境下默认的Python执行环境。所以在很多人的概念里CPython就是Python,也就想当然的把 GIL 归结为Python语言的缺陷。所以这里要先明确一点:GIL并不是Python的特性,Python完全可以不依赖于GIL
因为Python的线程虽然是真正的线程,但解释器执行代码时,有一个GIL锁:Global Interpreter Lock,任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。
多个线程如果共享一个变量,它们都有可能对变量进行修改,但高级语言的一条语句在CPU执行时是若干步,即使一个简单的计算common = common + 1也分为至少两步:
1. 求和common和1并将值转存到一个临时变量
2. 将临时变量值赋给common
由于线程是交替执行的,所以循环次数足够多时可能出现一个线程过程中执行另一个线程的第一步或第二步,如下:
import time,threadingcommon = 0def change(n): global common for i in range(100000): common = common + n common = common - nt1 = threading.Thread(target=change,args=(5,))t2 = threading.Thread(target=change,args=(8,))t1.start()t2.start()t1.join()t2.join()print common
运行结果如下:
261
所以我们运用线程锁(thrading.Lock())
import time,threadingcommon = 0lock = threading.Lock()def change(n): global common for i in range(100000): lock.acquire() try: common = common + n common = common - n #一定会释放锁 finally: lock.release()t1 = threading.Thread(target=change,args=(5,))t2 = threading.Thread(target=change,args=(8,))t1.start()t2.start()t1.join()t2.join()print common
运行结果为0
GIL解决了线程间数据一致性和状态同步的困难,但无疑大多数情况下它是低效的,但当大家开始抱怨并试图去拆分和去除GIL的时候,却发现大量库代码开发者已经重度依赖GIL而非常难以去除了。所以GIL的现存更多的是历史原因.
- Python并发机制(二)——多线程
- python并发的痛——多线程
- python并发的痛——多线程
- python并发的痛——多线程
- java多线程并发机制
- [Boost基础]并发编程——Thread多线程(二)
- java多线程并发(二)——线程池Executors
- 深入浅出Java并发包—锁机制(二)
- 多线程&并发(二)
- python 多线程并发
- python多线程并发学习
- 多线程并发内部实现机制
- Python多线程(2)——线程同步机制
- 多线程——GCD(并发)
- python多线程机制
- Python多线程机制
- python多线程机制
- JAVA多线程—并发集合
- JSP页面间传值、前后端传值及EL表达式
- histogramequalization
- python_list 之 基本操作
- 关于学习Hadoop中未总结的资料
- Oracle创建自增长主键
- Python并发机制(二)——多线程
- Qt: QLineEdit圆角边框,选中时变色,显示图标
- Python爬虫入门七之正则表达式
- 第十二周项目一递归方法实现逆序
- Hadoop集群系列(目录)
- 学习Hadoop不错的系列文章
- Xcode8更新约束
- C++53
- leetcode_效率题解_148. Sort List_(链表归并排序)