1.先验证GIL的存在
from threading import Thread, Lock
import time
money = 100deftask():
global money
money -= 1for i inrange(100): # 创建一百个线程
t = Thread(target=task)
t.start()
print(money)
2.验证加锁
from threading import Thread, Lock
import time
money = 100
mutex = Lock()
deftask():
global money
mutex.acquire()
time.sleep(0.1)
money -= 1
mutex.release()
t_list = []
for i inrange(100):
t = Thread(target=task)
t.start()
t_list.append(t)
for t in t_list:
t.join()
print(money)
print(t_list)
验证多线程作用
两个前提
cpu的个数:单个、多个
任务类型:IO密集型、计算密集型
# 单个cpu
多个IO密集型任务
多进程:浪费资源 无法利用多个cpu
多线程:节约资源 切换+保存状态
多个计算密集型任务
多进程:耗时更长 创建进程的消耗+切换消耗
多线程:耗时较短 切换消耗
# 多个cpu
多个IO密集型任务
多进程:浪费资源 多个CPU无用武之地
多线程:节省资源 切换+保存状态
多个计算密集型任务
多进程:利用多核 速度更快
多线程:速度较慢
结论:多进程和多线程都有具体的应用场景 尤其是多线程并不是没有用!
from threading import Thread
from multiprocessing import Process
import os
import time
defwork():
res = 1for i inrange(1, 100000):
res *= i
# 进程if __name__ == '__main__':
# print(os.cpu_count()) # 4 cpu个数
start_time = time.time()
p_list = []
for i inrange(4):
p = Process(target=work)
p.start()
p_list.append(p)
for p in p_list:
p.join()
print('总耗时:%s' % (time.time() - start_time))
# 线程
start_time = time.time()
p_list = []
for i inrange(4):
p = Thread(target=work)
p.start()
p_list.append(p)
for p in p_list:
p.join()
print('总耗时:%s' % (time.time() - start_time))
计算密集型
多进程:4.407211065292358
多线程:11.889238595962524
多进程更好
defwork():
time.sleep(1)
if __name__ == '__main__':
start_time = time.time()
t_list = []
for i inrange(100):
t = Thread(target=work)
t.start()
for t in t_list:
t.join()
print('总耗时:%s' % (time.time() - start_time))
start_time = time.time()
p_list = []
for i inrange(100):
p = Process(target=work)
p.start()
for p in p_list:
p.join()
print('总耗时:%s' % (time.time() - start_time))
IO密集型
多线程:0.013965368270874023
多进程:0.3231351375579834
多线程更好
死锁现象
from threading import Thread, Lock
import time
mutexA = Lock()
mutexB = Lock()
classMyThread(Thread):
defrun(self):
self.f1()
self.f2()
deff1(self):
mutexA.acquire()
print(f'{self.name}抢到了A锁')
mutexB.acquire()
print(f'{self.name}抢到了B锁')
mutexB.release()
mutexA.release()
deff2(self):
mutexB.acquire()
print(f'{self.name}抢到了B锁')
time.sleep(2)
mutexA.acquire()
print(f'{self.name}抢到了A锁')
mutexA.release()
mutexB.release()
for i inrange(20):
t = MyThread()
t.start()
信号量(了解)
信号量在不同的知识体系中 展示出来的功能是不一样的
eg:
在并发编程中信号量意思是多把互斥锁
在django框架中信号量意思是达到某个条件自动触发特定功能
"""
如果将自定义互斥锁比喻成是单个厕所(一个坑位)
那么信号量相当于是公共厕所(多个坑位)
"""from threading import Thread, Semaphore
import time
import random
sp = Semaphore(5) # 创建一个有五个坑位(带门的)的公共厕所deftask(name):
sp.acquire() # 抢锁print('%s正在蹲坑' % name)
time.sleep(random.randint(1, 5))
sp.release() # 放锁for i inrange(1, 31):
t = Thread(target=task, args=('伞兵%s号' % i, ))
t.start()
# 只要是跟锁相关的几乎都不会让我们自己去写 后期还是用模块
event事件(了解)
子线程的运行可以由其他子线程决定
# from threading import Thread, Semaphore
# import time
# import random
#
# sp = Semaphore(5)
#
# def task(name):
# sp.acquire()
# print('%s正在蹲坑'% name)
# time.sleep(random.randint(1, 5))
#
# for i in range(1, 30):
# t = Thread(target=task, args=('李松稳%s号'% i,))
# t.start()
from threading import Thread, Event
import time
event = Event()
def light():
print('红灯')
time.sleep(2)
print('绿灯')
event.set()
def car(name):
print('%s正在等红灯' % name)
event.wait()
print('%s冲压' % name)
t = Thread(target=light)
t.start()
for i in range(15):
t = Thread(target=car, args=('%i' % i,))
t.start()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人