#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