Python2.7中有两个常用的多线程库Multiprocessing,Threading。在Python中,线程和进程的区别在于线程模块使用线程,进程模块使用进程233,不开玩笑,这是StackOverFlow上的解释。说重点,线程使用相同的内存空间,而进程使用不同的。这也就让进程之间传对象稍有点困难。当然,由于线程共享内存空间,那么必须要考虑线程安全。
thread thread算是轻量级的线程模块,它提供较为底层的多线程实现方案。使用start_new_thread(function, args[, kwargs])实现线程。使用allocate_lock()可以得到一个锁对象,用acquire()和release()来加锁和释放锁,用locked()来判断释放有锁。一把锁只能被一个线程得到,所以利用锁可以避免多个线程对同一资源的同时操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import threadfrom time import sleepdef addLock (lock) : lock.acquire() print lock.locked() sleep(1 ) lock.release() def main () : lock = thread.allocate() thread.start_new(addLock,(lock,)) thread.start_new(addLock,(lock,)) sleep(3 ) if __name__ == '__main__' : main()
threading threading作为一个更高级的模块,提供了一些thread没有的功能。threading中有两种锁,如threading.Lock(), threading.RLock()。
Lock 这里lock和thread模块里类似。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import threadingdef addLock (lock) : print lock.acquire(False ) def main () : lock = threading.Lock() t1 = threading.Thread(target=addLock, args=(lock,)) t2 = threading.Thread(target=addLock, args=(lock,)) t1.run() t2.run() if __name__ == '__main__' : main()
以上代码演示了利用Threading模块来确定一把锁只能被获得一次。
RLock RLock是可重入锁(reentrant lock),acquire()能够不被阻塞的被同一个线程调用多次。要注意的是release()需要调用与acquire()相同的次数才能释放锁。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import threading,timerlock=threading.RLock() result=[] def step1 () : global result if rlock.acquire(): result.append('step1' ) time.sleep(0 ) rlock.release() def step2 () : global result if rlock.acquire(): result.append('step2' ) time.sleep(0 ) rlock.release() def showresult () : print threading.current_thread() if rlock.acquire(): step1() step2() rlock.release() print result def clearresult () : global result if rlock.acquire(): result=None time.sleep(1 ) rlock.release() print threading.current_thread() print result t1=threading.Thread(target=showresult) t2=threading.Thread(target=clearresult) t1.start() t2.start()
Condition 条件同步机制是指:一个线程等待特定条件,而另一个线程发出特定条件满足的信号。 解释条件同步机制的一个很好的例子就是生产者/消费者(producer/consumer)模型。
Semaphore 信号量同步基于内部计数器,每调用一次acquire(),计数器减1;每调用一次release(),计数器加1.当计数器为0时,acquire()调用被阻塞。
Event 基于事件的同步是指:一个线程发送/传递事件,另外的线程等待事件的触发。在set()时, 其他线程就被唤醒执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 import threading, timeimport randomclass Producer (threading.Thread) : """ 向列表中生产随机整数 """ def __init__ (self, integers, event) : """ 构造器 @param integers 整数列表 @param event 事件同步对象 """ threading.Thread.__init__(self) self.integers = integers self.event = event def run (self) : """ 实现Thread的run方法。在随机时间向列表中添加一个随机整数 """ while True : integer = random.randint(0 , 256 ) self.integers.append(integer) print '%d appended to list by %s' % (integer, self.name) print 'event set by %s' % self.name self.event.set() self.event.clear() print 'event cleared by %s' % self.name time.sleep(1 ) class Consumer (threading.Thread) : """ 从列表中消费整数 """ def __init__ (self, integers, event) : """ 构造器 @param integers 整数列表 @param event 事件同步对象 """ threading.Thread.__init__(self) self.integers = integers self.event = event def run (self) : """ 实现Thread的run()方法,从列表中消费整数 """ while True : self.event.wait() try : integer = self.integers.pop() print '%d popped from list by %s' % (integer, self.name) except IndexError: time.sleep(1 ) def main () : integers = [] event = threading.Event() t1 = Producer(integers, event) t2 = Consumer(integers, event) t1.start() t2.start() t1.join() t2.join() if __name__ == '__main__' : main()