Python多线程和Python的锁
Python多线程
Python中实现多线程有两种方式,一种基于_thread模块(在Python2.x版本中为thread模块,没有下划线)的start_new_thread()函数,另一种基于threading模块的Thread类。
其实Python的多线程编程不能真正利用多核的CPU,但是用开源模块使你的计算压力分布到多核CPU上.........
一.使用start_new_thread()实现线程,是比较底层的实现方式,所有线程共享他们global数据,为了达到同步,模块也提供了简单的锁机制
| _thread.start_new_thread(function, args[, kwargs]) |
| 启动一个新的进程,并返回其标识符. 线程执行的函数需要的参数由args(必须为一个元组)提供,亦可通过可选参数kwargs提供关键字参数组 成的字典。当函数返回时,启动的线程也 停止退出。如果函数中存在未处理异常,会打印堆栈跟踪后线程停止退出(其他线程继续执行)。 |
其中线程标识符是一个非0整数,并没有直接意思,可以当作从一个线程组成的特殊字典中索引本线程的一个key,也可用_thread.get_ident()得到,在线程退出后,标识符会被系统回收。在线程执行过程中可以调用_thread.exit()终止本线程的执行。
- import _thread
- import time
- def threadFunction(count):
- for i in range(count):
- print('进程id为%d的打印%d'%(_thread.get_ident(),i))
- i-=1
- time.sleep(0.1)
- def begin():
- ident1=_thread.start_new_thread(threadFunction,(100,))
- print('启动标识符为%d的进程'%(ident1,))
- ident2=_thread.start_new_thread(threadFunction,(100,))
- print('启动标识符为%d的进程'%(ident2,))
- if __name__ == '__main__':
- begin()
二.使用Thread类来实现多线程,这种方式是对_thread模块(如果没有_thread,则为dummy_threading)的高级封装,在这种方式下我们需创建新类继承threading.Thread,和java一样重写threading.Thread的run方法即可.启动线程用线程的start方法,它会调用我们重写的run方法.
- class MyThread(threading.Thread):
- '''只能重写__init__ 和 run 两个方法'''
- def __init__(self,name):
- threading.Thread.__init__(self)
- self.name=name
- self.bool_stop=False
- def run(self):
- while not self.bool_stop:
- print('进程%s,于%s'%(self.name,time.asctime()))
- time.sleep(1)
- def stop(self):
- self.bool_stop = True
- if __name__ == '__main__':
- th1=MyThread('one')
- th2=MyThread('two')
- th1.start()
- th2.start()
Thread类还定义了以下常用方法与属性:
| Thread.getName() \Thread.setName() |
| 老方式用于获取和设置线程的名称,官方建议用Thread.name替代 |
| Thread.ident |
| 获取线程的标识符。只有在调用start()方法执行后才有效,否则返回None。 |
| Thread.is_alive() |
| 判断线程是否是激活的。 |
| Thread.join([timeout]) |
| 调用Thread.join将会使主调线程堵塞,直到被调用线程运行结束或超时。参数timeout是一个数值类型,表示超时时间,如果未提供该参数,那么主调线程将一直堵塞到被调线程结束。 |
Python中的锁
先用_thread模块的Lock锁来实现生产者消费者问题,Lock对象是Python提供的低级线程控制工具,使用起来非常简单,只需下面3条语句即可:
| _thread.allocate_lock()返回一个新Lock对象,即为一个新锁 |
| lock.acquire() 相当于P操作,得到一个锁, |
| lock.release()相当于V操作,释放一个锁 |
代码如下:
- import _thread,time,random
- dish=0
- lock = _thread.allocate_lock()
- def producerFunction():
- '''如果投的筛子比0.2大,则向盘子中增加一个苹果'''
- global lock,dish
- while True:
- if(random.random() > 0.1):
- lock.acquire()
- if dish < 100:
- dish+=1
- print('生产者增加了一个苹果,现在有%d个苹果'%(dish,))
- lock.release()
- time.sleep(random.random()*3)
- def consumerFunction():
- '''如果投的筛子比0.5大,则从盘子中取一个苹果'''
- global lock,dish
- while True:
- if(random.random() > 0.9):
- lock.acquire()
- if dish > 0:
- dish-=1
- print('消费者拿走一个苹果现,在有%d个苹果'%(dish,))
- lock.release()
- time.sleep(random.random()*3)
- def begin():
- ident1=_thread.start_new_thread(producerFunction,())
- ident2=_thread.start_new_thread(consumerFunction,())
- if __name__ == '__main__':
- begin()
另一个较高级的锁为RLock锁,RLock对象内部维护着一个Lock对象,它是一种可重入的对象。对于Lock对象而言,如果一个线程连续两次进行acquire操作,那么由于第一次acquire之后没有release,第二次acquire将挂起线程。这会导致Lock对象永远不会release,使得线程死锁。RLock对象允许一个线程多次对其进行acquire操作,因为在其内部通过一个counter变量维护着线程acquire的次数。而且每一次的acquire操作必须有一个release操作与之对应,在所有的release操作完成之后,别的线程才能申请该RLock对象。
threading模块对Lock也提供和封装,提供了更高级的同步方式(可以理解为更高级的锁),包括threading.Event和threading.Condition,其中threading.Event为提供了简单的同步方式:一个进程标记event,其他进程等待,只需下面的几个方法即可:
| Event.wait([timeout]) |
| 堵塞线程,直到Event对象内部标识位被设为True或超时(如果提供了参数timeout)。 |
| Event.set() |
| 将标识号设为Ture |
| Event.clear() |
| 设为标识符False |
threading.Condition 可以把Condiftion理解为一把高级的琐,它提供了比Lock, RLock更高级的功能,允许我们能够控制复杂的线程同步问题。threadiong.Condition在内部维护一个琐对象(默认是RLock),可以在创建Condigtion对象的时候把琐对象作为参数传入。Condition也提供了acquire, release方法,其含义与琐的acquire, release方法一致,其实它只是简单的调用内部琐对象的对应的方法而已。Condition还提供了如下方法(特别要注意:这些方法只有在占用琐(acquire)之后才能调用,否则将会报RuntimeError异常。):
| Condition.wait([timeout]): |
| wait方法释放内部所占用的琐,同时线程被挂起,直至接收到通知被唤醒或超时(如果提供了timeout参数的话)。当线程被唤醒并重新占有琐的时候,程序才会继续执行下去。 |
| Condition.notify(): |
| 唤醒一个挂起的线程(如果存在挂起的线程)。注意:notify()方法不会释放所占用的琐。 |
| Condition.notify_all() |
| 唤醒所有挂起的线程(如果存在挂起的线程)。注意:这些方法不会释放所占用的琐。 |
Python多线程和Python的锁的更多相关文章
- python 多线程中的同步锁 Lock Rlock Semaphore Event Conditio
摘要:在使用多线程的应用下,如何保证线程安全,以及线程之间的同步,或者访问共享变量等问题是十分棘手的问题,也是使用多线程下面临的问题,如果处理不好,会带来较严重的后果,使用python多线程中提供Lo ...
- [Python 多线程] GIL全局解释器锁 (十三)
Queue 标准库queue模块,提供FIFO(先进先出)的Queue.LIFO(后进先出)的队列.优先队列. Queue类是线程安全的,适用于多线程间安全的交换数据.内部使用了Lock和Condit ...
- [Python 多线程] Lock、阻塞锁、非阻塞锁 (八)
线程同步技术: 解决多个线程争抢同一个资源的情况,线程协作工作.一份数据同一时刻只能有一个线程处理. 解决线程同步的几种方法: Lock.RLock.Condition.Barrier.semapho ...
- python多线程与多进程及其区别
个人一直觉得对学习任何知识而言,概念是相当重要的.掌握了概念和原理,细节可以留给实践去推敲.掌握的关键在于理解,通过具体的实例和实际操作来感性的体会概念和原理可以起到很好的效果.本文通过一些具体的例子 ...
- python多线程同步实例分析
进程之间通信与线程同步是一个历久弥新的话题,对编程稍有了解应该都知道,但是细说又说不清.一方面除了工作中可能用的比较少,另一方面就是这些概念牵涉到的东西比较多,而且相对较深.网络编程,服务端编程,并发 ...
- 初识python多线程
目录 GIL锁 Thread类构造方法 Lock类.Rlock类 参考: python3多线程--官方教程中文版 python多线程-1 python多线程-2.1 python多线程-2.2 pyt ...
- python多线程几种方法实现
python多线程编程 Python多线程编程中常用方法: 1.join()方法:如果一个线程或者在函数执行的过程中调用另一个线程,并且希望待其完成操作后才能执行,那么在调用线程的时就可以使用被调线程 ...
- 一篇文章 图解Python 玩转Python
0 Python 解释器:1.Python数据结构:2.变量与运算符3 Python 流程控制 4 Python 文件处理5 python 输入输出6 Python 异常7 Python 函数和模块8 ...
- python多线程threading.Lock锁用法实例
本文实例讲述了python多线程threading.Lock锁的用法实例,分享给大家供大家参考.具体分析如下: python的锁可以独立提取出来 mutex = threading.Lock() #锁 ...
随机推荐
- ios UIView常用动画效果
一 //调用 1 2 3 4 5 6 if(m_viewScenario.superview == nil)<br>{ m_viewScenario.alpha = 1.0; ...
- Rebound-Android的弹簧动画库
Rebound是facebook出品的一个弹簧动画库,与之对应的IOS版本有一个pop动画库,也是非常的强大给力.Facebook真是互联网企业中的楷模,开源了很多的实用开源库,大赞一个!!! 讲解R ...
- Java学习笔记之:Java简介
一.引言 Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称.由James Gosling和同事们共同研发,并在1995年正式推出. ...
- 确认某端口占用情况并结束相应进程(Windows)
(1)确认某端口是否被占用 (2)通过查找对应的PID号,定位是哪一个进程在使用该端口 (3)通过PID号结束该进程 # 查找端口2000是否被占用C:\Users\tdcqma>netstat ...
- 转:Servlet的url匹配以及url-pattern详解
Servlet是J2EE开发中常用的技术,使用方便,配置简单,老少皆宜.估计大多数朋友都是直接配置用,也没有关心过具体的细节,今天遇到一个问题,上网查了servlet的规范才发现,servlet中的u ...
- Btrace入门到熟练小工完全指南
BTrace是神器,每一个需要每天解决线上问题,但完全不用BTrace的Java工程师,都是可疑的. BTrace的最大好处,是可以通过自己编写的脚本,获取应用的一切调用信息.而不需要不断地修改代码, ...
- opencv求取RGB分量
需要注意的是下面r,b,g的类型和顺序 须用IPL_DEPTH_8U类型创建图像且[0][1][2]分量分别是b,g,r. 另外多谢郑乾师兄帮我发现了IPL_DEPTH_8U问题 uchar r,b, ...
- HS-T912 adb 连接配置
手机丢了,花300大洋买的新手机阿...不讨论好不好用,只说怎么用. 安装驱动 linux 跳过 插上电脑,在__通知__里面打开__USB 连接__,会弹出__USB 设置__对话框. 选择__海信 ...
- C++ 11 vlearning
1.新增算术类型 longlong,最小不比long小,一般为64位. 2.列表初始化 int units_sold = {0};或者 int units_sold{0};非11标准 ...
- 详谈 Jquery Ajax 异步处理Json数据.
啥叫异步,啥叫Ajax.咱不谈啥XMLHTTPRequest.通俗讲异步就是前台页面javascript能调用后台方法.这样就达到了无刷新.所谓的Ajax.这里我们讲二种方法 方法一:(微软有自带Aj ...