线程和进程的关系python
1.地址空间和其余资源:进程之间相互独立,同一进程的各线程之间共享,某进程内的线程在其余进程不可见多线程
2.通讯:进程间的通讯IPC,线程间能够直接写进程数据(如全局变量)来通讯须要加锁保证数据一致并发
3.调度和切换:线程上下文切换比进程快不少ui
4.在多线程操做系统中,进程不是一个可执行的实体,真正去执行程序的不是进程是线程,进程就是一个线程的容器spa
线程的主要特色:操作系统
1.轻型实体线程
2.独立调度和分派的基本单位code
3.共享进程资源blog
4.可并发执行递归
线程的建立
两种方法:
from threading import Thread class MyThread(Thread): def __init__(self,n): super().__init__() self.n=n def run(self): print(self.n) if __name__ == '__main__': t=MyThread(100) t.start() 第二种: from threading import Thread def func(n): print(n) if __name__ == '__main__': t=Thread(target=func,args=(100,)) t.start()
死锁现象及递归锁:
import time from threading import Thread,Lock class MyThread(Thread): def __init__(self,lockA,lockB): super().__init__() self.lockA=lockA self.lockB=lockB pass def run(self): self.f1() self.f2() def f1(self): self.lockA.acquire() print("我拿了A锁") self.lockB. acquire() print("我是一个很好的客户") self.lockB.release() self.lockA.release() def f2(self): self.lockB.acquire() time.sleep(0.1) print("我拿到了B锁") self.lockA.acquire() print("我是好人") self.lockA.release() self.lockB.release() if __name__ == '__main__': lockA=Lock() lockB=Lock() t1=MyThread(lockA,lockB) t1.start() t2=MyThread(lockA,lockB) t2.start() print("我是经理")
递归锁,在Python中为了支持在同一线程中屡次请求同一资源,python提供了可重入锁RLock。
这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源能够被屡次require。直到一个线程全部的acquire都被release,其余的线程才能得到资源。上面的例子若是使用RLock代替Lock,则不会发生死锁:
守护线程:
不管是进程仍是线程,都遵循:守护xx会等待主xx运行完毕后被销毁。须要强调的是:运行完毕并不是终止运行
1 主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),而后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(不然会产生僵尸进程),才会结束,
#2 主线程在其余非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。由于主线程的结束意味着进程的结束,进程总体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束,由于进程执行结束是要回收资源的,全部必须确保你里面的非守护子线程所有执行完毕。