线程和进程概念
进程:数据隔离,资源分配的最小单位,可以利用多核,操作系统调度,开启关闭切换时间消耗大
multiprocessing 如何开启进程 start join
进程有数据不安全问题Lock
进程之间可以通信ipc
队列(安全) 管道(不安全)
第三方工具
进程之间可以通过Manager类实现数据共享
一般情况下开启的进程数不会超过cpu个数的两倍
线程
能被操作系统调度(给CPU执行)的最小单位
同一个进程中的多个线程能同时被cpu执行
数据共享,操作系统调度的最小单位可以利用多核,操作系统调度,
数据不安全,开启关闭切换时间消耗小
在CPython中的多线程 - 节省io操作的时间
gc 垃圾回收机制
引用计数 分代回收
全局解释器锁的出现主要是为了完成gc的回收机制,
对不同线程的引用计数的变化记录的更加准确
全局解释器锁 GIL(global interpreter lock)
导致了同一个进程中的多个线程只能有一个线程能真正被cpu执行
节省的是io操作的时间,而不是cpu计算的时间,因为cup的计算熟读非常快,
在大部分情况下,我们没有办法把一条进程中所有的io操作都规避掉
from threading import Thread, current_thread, enumerate, active_count import time def func(i): print(f"开始{i}", current_thread().ident) # 函数内拿线程id current_thread().ident time.sleep(1) print(f"结束{i}") for i in range(10): t1 = [] t = Thread(target=func, args=(i, )) t.start() print(t.ident) t1.append(t) print(enumerate(), active_count()) for t in t1: t.join() print("所有线程都执行完了") # 函数内拿线程id current_thread().ident # 线程不能从外部关闭 # 所有的子线程只能是自己执行完所有代码之后就关闭 # enumerate 列表 存储了所有活着的线程对象,包括主线程 # activ_count 储存了所有活着的线程个数 # 面向对象的方式启动线程 from threading import Thread class MyThread(Thread): def __init__(self,a,b): self.a = a self.b = b super().__init__() def run(self): print(self.ident) t = MyThread(1,2) t.start() t.run()
线程共享数据
""" 线程之间的数据共享 """ from threading import Thread n = 100 def func(): global n n -= 1 t1 = [] for i in range (100): t = Thread(target=func) t.start() t1.append(t) for t in t1: t.join() print(n)
线程数据不安全
from threading import Thread n = 0 def add(): for i in range(500000): global n n += 1 def sub(): for i in range(500000): global n n -= 1 tlist = [] for i in range(2): t1 = Thread(target=add) t1.start() t2 = Thread(target=sub) t2.start() tlist.append(t1) tlist.append(t2) for t in tlist: t.join() print(n)
线程锁
from threading import Thread, Lock n = 0 def add(lock): with lock: for i in range(500000): global n n += 1 def sub(lock): with lock: for i in range(500000): global n n -= 1 tlist = [] lock = Lock() for i in range(2): t1 = Thread(target=add,args=(lock, )) t1.start() t2 = Thread(target=sub, args=(lock, )) t2.start() tlist.append(t1) tlist.append(t2) for t in tlist: t.join() print(n)
守护线程
import time from threading import Thread def son(): while True: print("in son") time.sleep(1) t = Thread(target=son) t.daemon = True t.start() """ 主线程会先等子线程结束后结束 主线程结束进程就会结束 守护线程随着主线程的结束而结束 守护线程会在主线程的代码结束之后继续守护其他子线程 守护进程 会随着主进程的代码结束而结束 如果主进程代码结束之后还有其他子进程在运行,守护进程不守护 守护线程 随着主线程的结束而结束 如果主线程代码结束之后还有其他子线程在运行,守护线程也守护 守护进程和守护线程的结束原理不一样 守护进程需要主进程来回收资源 守护线程是随着进程的结束才结束的 其他子线程——》主线程结束——》主进程结束——》整个进程中的所有资源都被回收——》守护线程也会被回收 进程是资源分配单位 子进程都需要它的父进程来回收资源 线程都是进程中的资源 所有的线程都会随着进程的结束而被回收 """
标签:Thread,t1,print,线程,进程,守护 From: https://www.cnblogs.com/moon3496694/p/17145752.html