今日内容:
1、什么是线程?为何要有线程?怎么用线程?
2、开启线程的两种方式(*****)
3、线程vs进程(*****)
4、守护线程
5、互斥锁
6、死锁现象与解决方案-》递归锁
7、信号量
上节课复习
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
上节课复习: 1、守护进程 守护进程本质就是一个“子进程”,该“子进程”在父进程代码 运行完毕后就自动销毁 什么时候需要开启子进程? 当父进程中需要将一个任务并发执行时,可以开启子进程 什么时候需要将子进程设置为守护进程? 当父进程代码运行完毕后,子进程没有存在的意义了,就应该 将该子进程设置为守护进程 2、互斥锁 将多个并发的任务对修改共享数据的操作变成串行 牺牲了效率,但保证数据安全 互斥锁vs p.join() 1、互斥锁是局部串行 2、p.join()所有代码整体都是串行的 3、IPC机制(*****) 1、PIPE 2、队列:PIPE+锁 q=Queue() q.put() q.get() 4、生产者消费者模型(******) 该模型中包含两大重要的角色: 1、生产者:代表产生数据的任务 2、消费者:代表处理数据的任务 实现: 生产者---》队列《----消费者 该模型的优点: 1、实现了生产者与消费者的解耦和 2、平衡了生产者的生产力与消费者的消费力 什么时候用? 程序中存在明确的两类任务,一类负责造数据,另外义类负责处理数据 今日内容: 1、什么是线程?为何要有线程?怎么用线程? 2、开启线程的两种方式(*****) 3、线程vs进程(*****) 4、守护线程 5、互斥锁 6、死锁现象与解决方案-》递归锁 7、信号量
1、什么是线程?为何要有线程?怎么用线程?
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
01 什么是线程 进程其实不是一个执行单位,进程是一个资源单位 每个进程内自带一个线程,线程才是cpu上的执行单位 如果把操作系统比喻为一座工厂 在工厂内每造出一个车间===》启动一个进程 每个车间内至少有一条流水线===》每个进程内至少有一个线程 线程=》单指代码的执行过程 进程-》资源的申请与销毁的过程 02 进程vs线程 1、 内存共享or隔离 多个进程内存空间彼此隔离 同一进程下的多个线程共享该进程内的数据 2、创建速度 造线程的速度要远远快于造进程
2、开启线程的两种方式(*****)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from threading import Thread import time #方式一 def task(name): print('%s is running' %name) time.sleep(3) print('%s is done' %name) if __name__ == '__main__': t=Thread(target=task,args=('子线程',)) t.start() print('主') #方式二 # class Mythread(Thread): # def run(self): # print('%s is running' %self.name) # time.sleep(3) # print('%s is done' %self.name) # # if __name__ == '__main__': # t=Mythread() # t.start() # print('主')
3、线程vs进程(*****)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#1、线程的开启速度快 # from threading import Thread # from multiprocessing import Process # import time # # def task(name): # print('%s is running' %name) # time.sleep(3) # print('%s is done' %name) # # if __name__ == '__main__': # t=Thread(target=task,args=('子线程',)) # # t=Process(target=task,args=('子进程',)) # t.start() # print('主') #2、同一进程下的多个线程共享该进程内的数据 # from threading import Thread # import time # # x=100 # def task(): # global x # x=0 # # if __name__ == '__main__': # t=Thread(target=task,) # t.start() # # time.sleep(3) # t.join() # print('主',x)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# from threading import Thread,current_thread,active_count,enumerate # import time # # def task(name): # print('%s is running' %name) # # print(current_thread().name) #子线程查看子线程名 导入current_thread # time.sleep(1) # print('%s is done' %name) # if __name__ == '__main__': # t = Thread(target=task,args=('子线程',),name='t1') # t.start() # t.join() #主线程等待线程结束 # # print(t.is_alive()) 主线程查看子线程是否存活 # # print(t.name) #主线程查看子线程名 # # print(t.getName()) #主线程查看子线程名 # # print(active_count()) #主线程查看子线程活的数量 导入active_count # # print(enumerate()) #列表形式打印所有活着的线程 导入 enumerate # # current_thread().setName('xx') #修改当前线程名 导入current_thread # print('主',current_thread().name)
4、守护线程
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 守护线程会在本进程内所有非守护的线程都死掉了才跟着死 # 即: # 守护线程其实守护的是整个进程的运行周期(进程内所有的非守护线程都运行完毕) # from threading import Thread,current_thread # import time # # # def task(): # print('%s is running' % current_thread().name) # time.sleep(3) # print('%s is done' % current_thread().name) # # # if __name__ == '__main__': # t = Thread(target=task,name='守护线程') # t.daemon=True # t.start() # print('主') from threading import Thread import time def foo(): print(123) time.sleep(3) print("end123") def bar(): print(456) time.sleep(1) print("end456") t1=Thread(target=foo) t2=Thread(target=bar) t1.daemon=True t1.start() t2.start() print("main-------") ''' 123 456 main------- end456 '''
5、互斥锁
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from threading import Thread,Lock import time mutex=Lock() x=100 def task(): global x # mutex.acquire() temp=x time.sleep(0.1) x=temp-1 # mutex.release() if __name__ == '__main__': t_l=[] start=time.time() for i in range(100): t=Thread(target=task) t_l.append(t) t.start() for t in t_l: t.join() stop=time.time() print(x,stop-start)
6、死锁现象与解决方案-》递归锁
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from threading import Thread,Lock import time mutex=Lock() x=100 def task(): global x # mutex.acquire() temp=x time.sleep(0.1) x=temp-1 # mutex.release() if __name__ == '__main__': t_l=[] start=time.time() for i in range(100): t=Thread(target=task) t_l.append(t) t.start() for t in t_l: t.join() stop=time.time() print(x,stop-start)
7、信号量
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 信号量是控制同一时刻并发执行的任务数 #20个线程同时起来,但是同时执行的只有5个线程,之后释放几把锁就在执行几个线程 from threading import Thread,Semaphore,current_thread import time,random sm=Semaphore(5) #5把锁 def task(): with sm: print('%s 正在上厕所' %current_thread().name) time.sleep(random.randint(1,4)) if __name__ == '__main__': for i in range(20): t=Thread(target=task) t.start()