一、名字解释
Python虚拟机:也叫解释器主循环,控制Python代码的执行。
多线程:类似单CPU系统中运行多个进程。 任意时刻,只能有一个线程在解释器中运行。
全局解释器锁(GIL):保证同一个时刻只有一个线程在运行。
二、thread
#!/usr/bin/env python #import thread from time import sleep, ctime def loop0(): print "start loop 0 at:", ctime() sleep(4) print "end loop 0 at:", ctime() def loop1(): print "start loop 1 at:", ctime() sleep(2) print "end loop 1 at:",ctime() def main(): print "starting at:", ctime() loop0() loop1() #thread.start_new_thread(loop0,()) #thread.start_new_thread(loop1,()) #sleep(6) print "ending at:", ctime(); if __name__ == "__main__": main()
有thread,无锁:并发执行,共耗时4秒,需要主线程中手动sleep
#!/usr/bin/env python import thread from time import sleep, ctime secs = [4,2] def loop(nloop, nsec, lock): print "start loop ", nloop," at:", ctime() sleep(nsec) print "end loop ", nloop, " at:", ctime() lock.release() def main(): print "starting at:", ctime() nsecs = range(len(secs)) locks = [] for i in nsecs: lock = thread.allocate_lock() lock.acquire() locks.append(lock) for i in nsecs: thread.start_new_thread(loop, (i, secs[i], locks[i])) for i in nsecs: while locks[i].locked(): pass print "ending at:", ctime(); if __name__ == "__main__": main()
三、threading
3种创建线程方法
1. 创建一个Thread的实例,传给它一个函数
2. 创建一个Thread的实例,传给它一个可调用的类对象
3. 从Thread派生出一个子类,创建一个这个子类的实例
#!/usr/bin/env python import threading from time import sleep, ctime secs = [4,2] #class ThreadFunc(object): # def __init__(self, func, args, name=''): # self.name = name # self.func = func # self.args = args # # def __call__(self): # apply(self.func, self.args) def loop(nloop, nsec): print "start loop ", nloop, " at:", ctime() sleep(nsec) print "end loop ", nloop," at:", ctime() def main(): print "starting at:", ctime() nsecs = range(len(secs)) threads = [] for i in nsecs: #t = threading.Thread(target=ThreadFunc(loop, (i, secs[i]), loop.__name__)) t = threading.Thread(target=loop,args=(i,secs[i])) threads.append(t) for i in nsecs: threads[i].start() for i in nsecs: threads[i].join() print "ending at:", ctime(); if __name__ == "__main__": main()
四、threading.Lock
import threading
g_lock = threading.Lock()
g_lock.acquire()
g_lock.release()
import threading g_tickets = 100 g_lock = threading.Lock() def loop1(): global g_tickets global g_lock while True: g_lock.acquire() if g_tickets > 0: print("thread 1 sell tickets: %d" % (g_tickets)) g_tickets = g_tickets - 1 else: g_lock.release() break g_lock.release() def loop2(): global g_tickets global g_lock while True: g_lock.acquire() if g_tickets > 0: print("thread 2 sell tickets: %d" % (g_tickets)) g_tickets = g_tickets - 1 else: g_lock.release() break g_lock.release() def main(): t1 = threading.Thread(target=loop1, args=()); t2 = threading.Thread(target=loop2, args=()) t1.start() t2.start() t1.join() t2.join() if __name__ == "__main__": main()
五、尽量使用threading,避免使用thread
1. threading模块更为先进,对线程支持更完善,使用thread模块可能会与threading出现冲突。
2. thread模块同步原语少(只有一个),threading模块有很多。
3. thread,当主线程结束时,所有线程都被强制结束掉;threading模块能确保重要的子线程退出口进程再退出。
六、Queue
import Queue
queue = Queue.Queue(maxsize=10)
queue.put(num)
num = queue.get()
queue.qsize()
import threading import Queue import random import time queue = Queue.Queue(maxsize=10) def loop1(): while True: if queue.qsize() < 10: num = random.randint(1, 100) print("produce num: %d" % (num)) queue.put(num) time.sleep(random.randint(1,3)) def loop2(): while True: if queue.qsize > 0: num = queue.get() print("consumer num: %d" % (num)) time.sleep(random.randint(1,3)) def main(): t1 = threading.Thread(target=loop1, args=()) t2 = threading.Thread(target=loop2, args=()) t1.start() t2.start() t1.join() t2.join() if __name__ == "__main__": main()