import threading import time def run(n): print("task",n) time.sleep(2) t1=threading.Thread(target=run,args=("t1",))#一个参数也要用逗号 t2=threading.Thread(target=run,args=("t2",)) t1.start() t2.start() #最简单的多线程
过程的名字可以随便,但是在下面的类里面就必须用RUN
import threading import time class MyThread(threading.Thread): def __init__(self,n): super(MyThread,self).__init__() self.n=n def run(self):#如果是一个DEF 那么就可以是任意的名字,但是在类里面他就必须叫run print("running task:"%self.n) t1=MyThread('t1') t2=MyThread('t2') t1.start() t2.start()
这就是多线程的两种写法。
算程序运行的时间
import threading import time starttime=time.time() def run(n): print("task",n) time.sleep(2) for i in range(50): t=threading.Thread(target=run,args=("t%s"%i,))#一个参数也要用逗号 t.start() curenttime=time.time() cha=curenttime-starttime print("cost %s秒"%cha) #这样是测不出来运行时间的因为是并行的主线程和子线程没关系 都在运行
应该用
import threading import time starttime=time.time() def run(n): print("task",n) time.sleep(2) t_object=[] for i in range(50): t=threading.Thread(target=run,args=("t%s"%i,))#一个参数也要用逗号 t.start() t_object.append(t) for ii in t_object:#等待所有的线程都进行完 ii.join() print(ii,"结束") curenttime=time.time() cha=curenttime-starttime print("cost %s秒"%cha)
守护线程的意义
import threading import time starttime=time.time() def run(n): print("task",n) time.sleep(2) t_object=[] for i in range(50): t=threading.Thread(target=run,args=("t%s"%i,))#一个参数也要用逗号 t.setDaemon(True)#设置线程为守护线程,就是跟主线程关系不大主线程不会等他执行的结果,主线程执行完就完了,没守护线程什么事儿了。 t.start() t_object.append(t) for ii in t_object:#等待所有的线程都进行完 ii.join() print(ii,"结束") curenttime=time.time() cha=curenttime-starttime print("cost %s秒"%cha)
正常来讲,这个num结果应该是0, 但在python 2.7上多运行几次,会发现,最后打印出来的num结果不总是0,为什么每次运行的结果不一样呢? 哈,很简单,假设你有A,B两个线程,此时都 要对num 进行减1操作, 由于2个线程是并发同时运行的,所以2个线程很有可能同时拿走了num=100这个初始变量交给cpu去运算,当A线程去处完的结果是99,但此时B线程运算完的结果也是99,两个线程同时CPU运算的结果再赋值给num变量后,结果就都是99。那怎么办呢? 很简单,每个线程在要修改公共数据时,为了避免自己在还没改完的时候别人也来修改此数据,可以给这个数据加一把锁, 这样其它线程想修改此数据时就必须等待你修改完毕并把锁释放掉后才能再访问此数据。
*注:不要在3.x上运行,不知为什么,3.x上的结果总是正确的,可能是自动加了锁
import time import threading def addNum(): global num #在每个线程中都获取这个全局变量 print('--get num:',num ) time.sleep(1) lock.acquire() #修改数据前加锁 num -=1 #对此公共变量进行-1操作 lock.release() #修改后释放 num = 100 #设定一个共享变量 thread_list = [] lock = threading.Lock() #生成全局锁 for i in range(100): t = threading.Thread(target=addNum) t.start() thread_list.append(t) for t in thread_list: #等待所有线程执行完毕 t.join() print('final num:', num )
RLock(递归锁)
说白了就是在一个大锁中还要再包含子锁
import threading,time def run1(): print("grab the first part data") lock.acquire() global num num +=1 lock.release() return num def run2(): print("grab the second part data") lock.acquire() global num2 num2+=1 lock.release() return num2 def run3(): lock.acquire() res = run1() print('--------between run1 and run2-----') res2 = run2() lock.release() print(res,res2) if __name__ == '__main__': num,num2 = 0,0 lock = threading.RLock() for i in range(10): t = threading.Thread(target=run3) t.start() while threading.active_count() != 1: print(threading.active_count()) else: print('----all threads done---') print(num,num2)
Semaphore(信号量)
互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。
import threading,time def run(n): semaphore.acquire() time.sleep(1) print("run the thread: %s " %n) semaphore.release() if __name__ == '__main__': num= 0 semaphore = threading.BoundedSemaphore(5) #最多允许5个线程同时运行 for i in range(20): t = threading.Thread(target=run,args=(i,)) t.start() while threading.active_count() != 1: pass #print threading.active_count() else: print('----all threads done---') print(num)
通过Event来实现两个或多个线程间的交互,下面是一个红绿灯的例子,即起动一个线程做交通指挥灯,生成几个线程做车辆,车辆行驶按红灯停,绿灯行的规则。
import threading,time import random def light(): if not event.isSet(): event.set() #wait就不阻塞 #绿灯状态 count = 0 while True: if count < 10: print('