python多线程编程,通常使用thread和threading模块。thread模块想对较底层,threading模块对thread模块进行了封装,更便于使用。全部,一般多线程编程使用threading模块。python
(一)threading模块shell
Thread 线程类,这是咱们用的最多的一个类,你能够指定线程函数执行或者继承自它均可以实现子线程功能; Timer与Thread相似,但要等待一段时间后才开始运行; Lock 锁原语,这个咱们能够对全局变量互斥时使用; RLock 可重入锁,使单线程能够再次得到已经得到的锁; Condition 条件变量,能让一个线程停下来,等待其余线程知足某个“条件”; Event 通用的条件变量。多个线程能够等待某个事件发生,在事件发生后,全部的线程都被激活; Semaphore为等待锁的线程提供一个相似“等候室”的结构; BoundedSemaphore 与semaphore相似,但不容许超过初始值; Queue:实现了多生产者(Producer)、多消费者(Consumer)的队列,支持锁原语,可以在多个线程之间提供很好的同步支持。
(1)threading.Thread类编程
getName(self) 返回线程的名字 isAlive(self) 布尔标志,表示这个线程是否还在运行中 isDaemon(self) 返回线程的daemon标志 join(self, timeout=None) 程序挂起,直到线程结束,若是给出timeout,则最多阻塞timeout秒 run(self) 定义线程的功能函数 setDaemon(self, daemonic) 把线程的daemon标志设为daemonic setName(self, name) 设置线程的名字 start(self) 开始线程执行
(2)threading.Queue类多线程
Queue队列 LifoQueue后入先出(LIFO)队列 PriorityQueue 优先队列
(二)线程的建立函数
线程的建立通常有两种:①将建立的函数传递进threading.Thread()对象。②继承threading.Thread类,一般重写run()方法。ui
(1)使用threading.Thread(),实例化一个线程线程
# -*- coding: utf-8 -*- import threading # 使用threading.Thread(),实例化一个线程 def T(): print threading.current_thread().getName() # 建立线程对象 t1 = threading.Thread(target=T, name='tt11') # 启动线程 t1.start() t1.join()
(2)建立threading.Thread 的子类, 并覆盖run() 方法code
# -*- coding: utf-8 -*- import threading # 建立threading.Thread 的子类, 并覆盖run() 方法 class T(threading.Thread): # 重写父类run()方法 def run(self): print self.getName() # 实例化线程,并运行 t1 = T() t1.start()
(3)例子对象
# -*- coding: utf-8 -*- import threading class T(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): pass def main(): t = T() t.start() if __name__ == '__main__': main()
(4)join方法继承
用来阻塞上下文,直到该线程结束。
def join(self, timeout=None): pass
(5)setDaemon方法
守护线程 当咱们在程序运行中,执行一个主线程,若是主线程又建立一个子线程,主线程和子线程就分兵两路, 当主线程完成想退出时,会检验子线程是否完成。若是子线程未完成,则主线程会等待子线程完成后再退出。 可是有时候咱们须要的是,只要主线程完成了,无论子线程是否完成,都要和主线程一块儿退出, 这时就能够用setDaemon方法,并设置其参数为True。
(三)共享资源的访问
共享资源,互斥与同步。
(1)简单的threading.Lock() 锁
# -*- coding: utf-8 -*- import threading counter = 0 mutex = threading.Lock() class T(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): # 全局变量 global counter, mutex time.sleep(1) # 得到加锁 if mutex.acquire(): counter += 1 # 释放锁 mutex.release() def main(): t = T() t.start() if __name__ == '__main__': main()
当一个线程调用Lock对象的acquire()方法得到锁时,这把锁就进入“locked”状态。 由于每次只有一个线程1能够得到锁,因此若是此时另外一个线程2试图得到这个锁,该线程2就会变为“blo同步阻塞状态。 直到拥有锁的线程1调用锁的release()方法释放锁以后,该锁进入 “unlocked”状态。线程调度程序从处于同步阻塞状态的线程中选择一个来得到锁,并使得该线程进入运行(running)状态。
(2)可重入锁 threading.RLock()
当线程在得到加锁以后,又须要共享资源,须要再次加锁。但...
# -*- coding: utf-8 -*- import threading counter = 0 mutex = threading.Lock() # mutex = threading.RLock() class T(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): # 全局变量 global counter, mutex time.sleep(1) # 得到加锁 if mutex.acquire(): counter += 1 # 再次加锁 if mutex.acquire(): counter += 1 mutex.release() # 释放锁 mutex.release() def main(): t = T() t.start() if __name__ == '__main__': main()
此时程序会挂起,也就是造成了最简单死锁。 在Python中为了支持在同一线程中屡次请求同一资源,引入了‘可重入锁’。 count 记录了acquire的次数,从而使得资源能够被屡次require。 直到一个线程全部的acquire都被release,其余的线程才能得到资源。 # 源代码 def RLock(*args, **kwargs): return _RLock(*args, **kwargs) class _RLock(_Verbose): def __init__(self, verbose=None): _Verbose.__init__(self, verbose) self.__block = _allocate_lock() self.__owner = None self.__count = 0
(3)使用Condition实现复杂的同步
Condition被称为条件变量,除了提供与Lock相似的acquire和release方法外,还提供了wait和notify方法。 使用Condition的主要方式为: 线程首先acquire一个条件变量,而后判断一些条件。 若是条件不知足则wait; 若是条件知足,进行一些处理改变条件后,经过notify方法通知其余线程,其余处于wait状态的线程接到通知后会从新判断条件。 不断的重复这一过程,从而解决复杂的同步问题。
一个经典的例子。生产者消费者问题。(理解上述,代码其实很简单。)
import threading import time condition = threading.Condition() products = 0 class Producer(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): global condition, products while True: if condition.acquire(): if products < 10: products += 1; print "Producer(%s):deliver one, now products:%s" %(self.name, products) condition.notify() else: print "Producer(%s):already 10, stop deliver, now products:%s" %(self.name, products) condition.wait(); condition.release() time.sleep(2) class Consumer(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): global condition, products while True: if condition.acquire(): if products > 1: products -= 1 print "Consumer(%s):consume one, now products:%s" %(self.name, products) condition.notify() else: print "Consumer(%s):only 1, stop consume, products:%s" %(self.name, products) condition.wait(); condition.release() time.sleep(2) if __name__ == "__main__": for p in range(0, 2): p = Producer() p.start() for c in range(0, 10): c = Consumer() c.start()
(4)使用 threading.Event 实现线程间通讯
使用threading.Event可使一个线程等待其余线程的通知,咱们把这个Event传递到线程对象中, Event默认内置了一个标志,初始值为False。 一旦该线程经过wait()方法进入等待状态,直到另外一个线程调用该Event的set()方法将内置标志设置为True时, 该Event会通知全部等待状态的线程恢复运行。
import threading import time class MyThread(threading.Thread): def __init__(self, signal): threading.Thread.__init__(self) # 初始化 self.singal = signal def run(self): print "I am %s,I will sleep ..."%self.name # 进入等待状态 self.singal.wait() print "I am %s, I awake..." %self.name if __name__ == "__main__": # 初始 为 False singal = threading.Event() for t in range(0, 3): thread = MyThread(singal) thread.start() print "main thread sleep 3 seconds... " time.sleep(3) # 唤醒含有signal, 处于等待状态的线程 singal.set()
-- 2014年08月23日03:53:22