开启线程
一:什么是线程
在传统意义上,每一个进程有一个地址空间,而且地址默认就有一个控制线程
线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个过程是一个进程
车间负责把资源整合到一起,是一个资源单位,而一个车间内至少有一个流水线
流水线的工作需要电源,电源就相当于cpu
所以,进程知识用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),线程才是cpu上的执行单位
多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间
相当于一个车间内有多个地铁线,都共用一个车间的资源
例如:北京地铁与上海地铁是不同的进程,而北京地铁里的13号线是一个线程,北京地铁所有的线路共享北京地铁的所有资源,比如所有的乘客可以被所有线路拉。
二:线程的创建开销小
创建进程的开销要远大于线程?
如果我们的软件是一个工厂,该工厂有多条流水线,流水线工作需要电源,电源只有一个即cpu(单核)
一个车间就是一个进程,一个车间至少一条流水线(一个进程至少一个线程)
创建一个进程,就是创建一个车间(申请空间,该在空间内建至少一条流水线)
而建线程,就只是在一个车间内造一条流水线,无需申请空间,所以创建开销小
进程之间是竞争关系,线程之间是协作关系?
车间之间是竞争关系,线程之间是协作关系?
车间直接是竞争/抢电源的关系,竞争(不同的进程直接是竞争关系,是不同的程序写的程序运行的,迅雷抢占其他进程的网速,360把其他进程当做病毒干死)
一个车间的不同流水线式协同工作的关系(同一个进程的线程之间是合作关系,是同一个程序写的程序内开启动,迅雷内的线程是合作关系,不会自己干自己)
三开启线程的两种方式
# from multiprocessing import Process # from threading import Thread # import time # # def task(name): # print('%s is running' %name) # time.sleep(3) # # if __name__ == '__main__': # t=Thread(target=task,args=('egon',)) # # t=Process(target=task,args=('egon',)) # t.start() # print('主线程') from multiprocessing import Process from threading import Thread import time class MyThread(Thread): def run(self): print('%s is running' %self.name) time.sleep(3) if __name__ == '__main__': t=MyThread() t.start() print('主线程')
四 进程Vs线程
#1、瞅一瞅PID # from threading import Thread # import time,os # # def task(): # print('%s is running' %os.getpid()) # time.sleep(3) # # if __name__ == '__main__': # t=Thread(target=task,) # t.start() # print('主线程',os.getpid()) #2、线程创建开销小 #3、同一进程内的多个线程共享该进程内的资源 from threading import Thread import time,os x=1000 def task(): global x x=0 if __name__ == '__main__': t=Thread(target=task,) t.start() t.join() print('主线程',x)
五、线程对象的其他方法
from threading import Thread,current_thread,active_count,enumerate import time,os def task(): print('%s is running' %current_thread().name) time.sleep(3) if __name__ == '__main__': t1=Thread(target=task,name='第一个线程') t2=Thread(target=task,) t3=Thread(target=task,) t1.start() t2.start() t3.start() # print(t1.is_alive()) print(active_count()) print(enumerate()) print('主线程',current_thread().name)
六:守护线程
# from threading import Thread,current_thread # import time # # def task(): # print('%s is running' %current_thread().name) # time.sleep(3) # # if __name__ == '__main__': # t1=Thread(target=task,name='第一个线程') # t1.daemon = True # t1.start() # # print('主线程') from threading import Thread import time def foo(): print(123) time.sleep(5) print("end123") def bar(): print(456) time.sleep(3) print("end456") if __name__ == '__main__': t1=Thread(target=foo) t2=Thread(target=bar) t1.daemon=True t1.start() t2.start() print("main-------") ''' 123 456
七:线程互斥锁
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__': start=time.time() t_l=[] for i in range(100): t=Thread(target=task) t_l.append(t) t.start() for t in t_l: t.join() print('主',x) print(time.time()-start)
八:死锁现象与递归锁
from threading import Thread,Lock,RLock import time # mutexA=Lock() # mutexB=Lock() mutexA=mutexB=RLock() class MyThread(Thread): def run(self): self.f1() self.f2() def f1(self): mutexA.acquire() print('%s 拿到了A锁' %self.name) mutexB.acquire() print('%s 拿到了B锁' %self.name) mutexB.release() mutexA.release() def f2(self): mutexB.acquire() print('%s 拿到了B锁' %self.name) time.sleep(0.1) mutexA.acquire() print('%s 拿到了A锁' %self.name) mutexA.release() mutexB.release() if __name__ == '__main__': for i in range(10): t=MyThread() t.start() # t1=MyThread() # t1.start() # # t2=MyThread() # t2.start() # # t3=MyThread() # t3.start() print('主')
九:信号量
# from multiprocessing import Semaphore from threading import Thread,Semaphore,current_thread import time,random sm=Semaphore(5) def go_wc(): sm.acquire() print('%s 上厕所ing' %current_thread().getName()) time.sleep(random.randint(1,3)) sm.release() if __name__ == '__main__': for i in range(23): t=Thread(target=go_wc) t.start()