一、join方法
(1)开一个主线程
from threading import Thread,currentThread import time def walk(): print('%s is running'%currentThread().getName()) time.sleep(2) print('%s is done'%currentThread().getName()) if __name__ == '__main__': # for i in range(10): p=Thread(target=walk) p.start() p.join() print('主') #主线程在等p.join执行
(2)开多个主线程,并发运行
from threading import Thread,currentThread import time def walk(): print('%s is running'%currentThread().getName()) time.sleep(2) print('%s is done'%currentThread().getName()) if __name__ == '__main__': l=[] for i in range(10): p=Thread(target=walk) l.append(p) p.start() # p.join() #在p.start() 跟p.join()就会变为串行,一个一个的运行 for p in l: p.join() print('主')
(3)并发运行 互斥锁之锁局部的 ,用所只锁住你对共享数据修改的部分
加锁:
from threading import Thread,currentThread,Lock import time n=100 def walk(): # 并发运行 time.sleep(2) global n mutex.acquire() # 串行 temp=n time.sleep(0.01) n=temp-1 #数据可能同是减1,可能数据会乱 mutex.release() if __name__ == '__main__': mutex=Lock() l=[] start = time.time() for i in range(100): p=Thread(target=walk) l.append(p) p.start() for p in l: p.join() stop = time.time() print('n:%s run_time : %s' %(n,stop - start))
不加锁:
from threading import Thread,currentThread,Lock import time n=100 def walk(): time.sleep(2) global n # mutex.acquire() temp=n time.sleep(0.1) n=temp-1 #数据可能同是减1,可能数据会乱 # mutex.release() if __name__ == '__main__': mutex=Lock() start = time.time() for i in range(10): p=Thread(target=walk) p.start() p.join() stop = time.time() print('n:%s run_time : %s' %(n,stop - start)) #至少21秒
主线程运行完毕是在所有线程所在的进程内所有非守护线程运行完毕才运行
二、GIL本质是一把互斥锁,将并发转成串行,以此来控制同一时间内共享数据只能被一个任务修改,
进而保证数据的安全
from threading import Thread,currentThread,Lock import time n=100 def work(): time.sleep(2) global n time.sleep(0.5) mutex.acquire() temp=n time.sleep(0.1) n=temp-1 mutex.release() if __name__ == '__main__': mutex=Lock() t1=Thread(target=work) t2=Thread(target=work) t3=Thread(target=work) t1.start() t2.start() t3.start()
三、多线程性能测试
(1)'''
多进程
优点:可以利用多核
缺点:开销大
多线程
优点:开销小
缺点:不可以利用多核
'''
from multiprocessing import Process from threading import Thread import time def work(): res=0 for i in range(10000000): res+=i if __name__ == '__main__': l=[] start=time.time() for i in range(4): # p=Process(target=work) #0.9260530471801758 p=Thread(target=work) #0.9260530471801758 l.append(p) p.start() for p in l: p.join() stop=time.time() print('%s' %(stop-start))
from multiprocessing import Process from threading import Thread import time def work(): time.sleep(2) if __name__ == '__main__': l=[] start=time.time() for i in range(400): p=Process(target=work) # p=Thread(target=work) l.append(p) p.start() for p in l: p.join() stop=time.time() print('%s' %(stop-start))
(2)应用:
多线程用于IO密集型,如socket,爬虫,web
多进程用于计算密集型,如金融分析
四、死锁与递归锁
死锁:
from threading import Thread,RLock import time mutexA=RLock() class MyThread(Thread): def run(self): self.f1() self.f2() def f1(self): mutexA.acquire() print('%s 拿到A锁'%self.name) mutexA.acquire() print('%s 拿到B锁' % self.name) mutexA.release() mutexA.release() def f2(self): mutexA.acquire() print('%s 拿到A锁' % self.name) time.sleep(1) mutexA.acquire() print('%s 拿到B锁' % self.name) mutexA.release() mutexA.release() if __name__ == '__main__': for i in range(10): t=MyThread() t.start()
解决死锁的方法
递归锁:用RLock代替Lock
1 from threading import Lock,Thread,RLock 2 import time 3 # mutexA=Lock() 4 # mutexB=Lock() 5 mutexB=mutexA=RLock() 6 class MyThread(Thread): 7 def run(self): 8 self.f1() 9 self.f2() 10 def f1(self): 11 mutexA.acquire() 12 print('