python多线程3线程同步
#coding:gbk ''' Created on 2013-1-5 @author: Jimmy @note: Lock, RLock, Semaphore, Condition, Event and Queue 只是介绍怎么初始化和使用,完整代码可见MThread中的同步操作 ''' import threading import Queue if __name__ == "__main__": phone = 0 ''' A、多个线程使用同一个Lock, RLock, Semaphore, Condition, Event and Queue的对象; Lock, RLock, Semaphore是线程操作临界区的互斥方法; Event是线程间同步的方法 B、Lock,RLock,Semaphore(锁和信号)其中个人觉得使用RLock比较好,Lock和Semaphore是比较老,不在推荐使用了; C、Event有点复杂,有一个完整的例子在ThreadSynchronizationTest.py中;解释了Clear()的作用和控制特定的 D、Condition算是 Lock 和 Event 的杂交版本; ''' #1、锁:threading.Lock,threading.RLock的使用相同;不同点是Lock会死锁,RLock不会(Lock两次acquire,就死锁了;相反,RLock不会) lock = threading.Lock()#lock = threading.RLock() lock.acquire()#锁获取 phone += 1#互斥操作 lock.release()#释放锁 #2、信号:threading.Semaphore(是比较老的一种同步互斥方法,pv操作;Semaphore的api和锁api一样;信号不会<0 sem = threading.Semaphore()#初始化信号为1 sem.acquire()#信号减1 phone += 1#互斥操作 sem.release()#信号加1 #3、事件:threading.Event ''' 其实threading.Event和RLock、Lock和Semaphore使用场景是不同的。 Event是线程间协调同步的操作。一个线程wait()挂起等待某个资源(由另外一个线程控制);另外一个线程完成后操作Set() RLock是同一个线程中成对使用的,控制只有一个线程在一个时间操作临界资源 AAAA注:Set()后,所有的线程都会收到;要想只用一个线程获取到,要加Clear()操作 Clear()方法是比较重要的,要想只有一个线程获取信号,在wait()或者Set()操作后要Clear()下。 Set()后调用Clear()一定只有一个线程获取,Wait()后调用Clear()不一定(因为,不一定是该线程第一个执行) ''' event = threading.Event() event.wait()#线程1 event.set()#线程2 event.clear()#线程2 #3、事件:threading.Condition cond = threading.Condition() #RLock的属性 cond.acquire() cond.release() #Event的属性 cond.wait()#Wait until notified cond.notify()#Wake up a thread waiting on this condition cond.notifyAll()#Wake up all threads ==notify_all() #threading.Queue ''' Queue模块实现了一个支持多producer和多consumer的FIFO队列。当共享信息需要安全的在多线程之间交换时,Queue非常有用。 Queue的默认长度是无限的, 但是可以设置其构造函数的maxsize参数来设定其长度。 put: Queue的put方法在队尾插入,该方法的原型是:put( item[, block[, timeout]]) 如果可选参数block为true并且timeout为None(缺省值),线程被block,直到队列空出一个数据单元。如果timeout大于0,在timeout的时间内,仍然没有可用的数据单元, Full exception被抛出。反之,如果block参数为false(忽略timeout参数),item被立即加入到空闲数据单元中,如果没有空闲数据单元,Full exception被抛出。 get: Queue的get方法是从队首取数据,其参数和put方法一样。如果block参数为true且timeout为None(缺省值),线程被block,直到队列中有数据。 如果timeout大于0,在timeout时间内,仍然没有可取数据,Empty exception被抛出。 反之,如果block参数为false(忽略timeout参数),队列中的数据被立即取出。如果此时没有可取数据,Empty exception也会被抛出。 Queue.join() 实际上意味着等到队列为空,再执行别的操作 ''' queue = Queue.Queue() queue.get()#获取 queue.put()#插入 pass