线程
线程:
在操作系统中,每一个进程都有一个空间,而且每一个空间都有一个线程,进程是资源单位,代码的运行过程指的是线程(即进程运行指开辟空间存放资源,线程运行,cpu运行代码块),进程是线程的容器,一个进程内可以有多个线程,多个线程之间可以达到并发执行,线程是程序中一个单子执行单元,所以在启用上比进程快100倍
线程----------------->单指代码的执行过程
进程----------------->资源的申请与销毁的过程
开启线程有两种方式,整体跟进程差不多:
多个子线程也都是线程,因为都是主线程下的分支
线程可以不用main因为所有的线程都是共享一个进程下的资源
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class MyThread(Thread): def run(self):#跟进程一样都有一个函数名run print("%s is runnong"%self.name) time.sleep(2) print("%s is done" %self.name) if __name__ == '__main__': t=MyThread() t.start() print("主")
进程vs线程:
from threading import Thread from multiprocessing import Process import os,time def task(): print("%s is running" %os.getpid()) time.sleep(2) print("%s is done"%os.getpid()) if __name__ == '__main__': t=Thread(target=task) t.start() # t.join() print("主线程",os.getpid()) #线程中主线程的ID跟子线程的ID一样,先走子线程再走主线程 """ 打印结果 15592 is running 主线程 15592 15592 is done """ def done(): print("%s is running" %os.getpid()) time.sleep(2) print("%s is done"%os.getpid()) if __name__ == '__main__': p=Process(target=done) p.start() print("主进程",os.getpid()) #进程中主线程的ID跟子进程的ID不一样,先走主进程再走子进程 """ 打印结果 主进程 10004 7084 is running 7084 is done """
进程与线路共享情况:
from threading import Thread from multiprocessing import Process import os n=100 def work(): global n n=0 if __name__ == '__main__': p=Process(target=work) p.start() p.join() print("主进程",n) #子进程将n改为0,但仅仅改变了子进程的指,但是父进程的n依然还是100 t=Thread(target=work) t.start()#创造子线程 t.join() print("主线程",n) #查看结果为0,因为同一进程内的线程之间共享进程内的数据
1、内存共享or隔离
多个进程内存空间彼此隔离
同一个进程下的多个线程共享,该进程内的数据
2、创建速度
造线程的速度比造进程的速度快
线程比进程开启快的原因在于进程开去需要向操作系统发送信号,而线程不需要像进程那样去向操作系统发送信号,而是可以直接执行
3、主与子ID是否相同
进程中主进程与子进程ID不相同,进程中先走主进程再走子进程
线程中主线程与子线程ID相同,线程中先走子线程,再走主线程
守护线程:
from threading import Thread import time def foo(): print(123) time.sleep(1) print("end123") def bar(): print(456) time.sleep(3) print("end456") t1=Thread(target=foo) t2=Thread(target=bar) t1.daemon=True t1.start() t2.start() print("main-------") ''' 123 456 main------- end123 end456 '''
守护线程会在本进程内所有非守护线程都死掉了才跟着死
守护线程其实守护的是整个进程的运行周期(线程内所有的非守护线程都运行完毕)
互斥锁:
from threading import Thread,Lock import time x=100 mutex=Lock() def task(): global x temp=x time.sleep(1)#在有等待的地方,如果main下面没有join()会打印出错 x=temp-1 if __name__ == '__main__': t=Thread(target=task) t.start() t.join() print(x)
在线程中,加入时间睡眠后,如果不运用join()就会影响测试结果,因为计算在睡眠的下面,遇到睡眠后会先打印main下面的主线程print(x),也就造成了输入为100的打印结果,加上join()后(主线程要等待子线程运行完毕后再运行)得到的值是正确的99
from threading import Thread import time x = 100 def task(): global x temp = x time.sleep(1) temp -= 1 x=temp if __name__ == '__main__': tlst=[] for i in range(100): t = Thread(target=task) tlst.append(t) t.start() for i in range(len(tlst)): tlst[i].join() print(x)
通过放慢的方式可以看出,如果没有join()的情况下直接是显示100,在有join()等待子线程结束完毕之后再运行主线程是正确的显示
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from threading import Thread,Lock import time x=100 mutex=Lock() def task(): time.sleep(0.1) global x with mutex: x -= 1 if __name__ == '__main__': for i in range(100):#循环次数 t = Thread(target=task) t.start() t.join() print(x)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from threading import Thread,current_thread,active_count,enumerate import time def task(): print("%s 子线程原名" %current_thread().name) time.sleep(1) print("%s 子线程修改过后名字" %current_thread().name) if __name__ == '__main__': t=Thread(target=task) t.start() t.join() # print("判断线程是否存活",t.is_alive()) # print("显示主线程名字",current_thread().getName()) # print(t.name)#看当前线程的名字 # print("显示存活的线程数",active_count()) # print("将所有线程放入列表",enumerate()) # current_thread().setName("主线程")#修改主线程名字 # print("parent",current_thread().name),"我原名MainThread,现名主线程")
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from threading import Thread,Lock,active_count import time mutexA = Lock() mutexB = Lock() class MyThread(Thread): def run(self): self.f1() self.f2() def f1(self): mutexA.acquire() print("A") mutexB.acquire() print("B") mutexB.release() mutexA.release() def f2(self): mutexB.acquire() print("A") time.sleep(1) mutexA.acquire() print("B") mutexA.release() mutexB.release() if __name__ == '__main__': for i in range(10): t = MyThread() t.start() print(active_count())
from threading import Thread, active_count, RLock import time obj = RLock() mutexA = obj mutexB = obj class MyThread(Thread): def run(self): self.f1() self.f2() def f1(self): mutexA.acquire() print("A") mutexB.acquire() print("B") mutexB.release() mutexA.release() def f2(self): mutexB.acquire() print("A") time.sleep(1) mutexA.acquire() print("B") mutexA.release() mutexB.release() if __name__ == '__main__': for i in range(10): t = MyThread() t.start() print(active_count())
信号量
控制同一时间互斥锁的量,并且有人释放锁会有人马上拿到锁
from threading import Thread, Semaphore, current_thread import time import random sm = Semaphore(5) def task(): with sm: print("%s正在卫生间" % current_thread().name) time.sleep(random.random()) if __name__ == '__main__': for i in range(20): t = Thread(target=task) t.start()