线程(Thread)
线程是进程中执行任务的最小单位
一个进程至少有一个线程 也有可能有多个线程
举个具体的例子
进程就像一间工厂
线程是里面的工人 多线程就是一间工厂有多个工人
工人负责执行任务
多线程(MultiThreading)
多线程就是一个进程里面用多个线程
python用threading编写多线程
调用thread类创建新线程
thread类的参数跟process差不多
target代表目标函数 args代表传入参数 kwargs传入关键字参数
name是标记thread名称
相关方法也差不多
启动是用start 等待用join
我想补充说明run()跟start()的差别
process也有一样的东西
py:
import threading
def print_current_thread():
current = threading.current_thread()
print(f"Current thread: {current}")
t1 = threading.Thread(target=print_current_thread)
t1.run()
t2 = threading.Thread(target=print_current_thread)
t2.start()
t2.join()
输出:
Current thread: <_MainThread(MainThread, started 14028)>
Current thread: <Thread(Thread-2 (print_current_thread), started 20984)>
从输出结果 我们可以发现run是直接执行当前线程 start才会启动新线程并执行
process的run跟start也有相同差异
再来说明lock
多线程与多进程最大差异在于资源共用
多进程会把整包东西复制到子进程
多线程则会共用资源 包括变量
所以会发生下面的问题:
import time, threading
# 假定这是你的银行存款:
balance = 0
def change_it(n):
# 先存后取,结果应该为0:
global balance
balance = balance + n
balance = balance - n
def run_thread(n):
for i in range(10000000):
change_it(n)
t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)
这程式码是两个线程对balance做加减
理论上 这结果是0
但实际并非如此
python中一行程式码传到cpu
诸如 balance = balance + n
往底层走会变成:
x为临时变量
x = balance + n
balance = x
所以放回原本程式码
两个线程交错就可能变成:
初始值 balance = 0
t1: x1 = balance + 5 # x1 = 0 + 5 = 5
t2: x2 = balance + 8 # x2 = 0 + 8 = 8
t2: balance = x2 # balance = 8
t1: balance = x1 # balance = 5
t1: x1 = balance - 5 # x1 = 5 - 5 = 0
t1: balance = x1 # balance = 0
t2: x2 = balance - 8 # x2 = 0 - 8 = -8
t2: balance = x2 # balance = -8
结果 balance = -8
线程的问题大致是这样
所以我们就要加个锁
balance = 0
lock = threading.Lock()
def run_thread(n):
for i in range(100000):
# 先要获取锁:
lock.acquire()
try:
# 放心地改吧:
change_it(n)
finally:
# 改完了一定要释放锁:
lock.release()
锁的函数跟process差不多 不另行说明
大致这样ㄅ gil之后再说 先吃饭
参考资料:
https://liaoxuefeng.com/books/python/process-thread/thread/index.html
https://docs.python.org/3/library/threading.html#rlock-objects