线程处理IO密集型任务
import threading
import time
def foo(something):
print(something)
time.sleep(1)
begin_time = time.time()
'''
#总消耗时长: 2.001000165939331
foo("磁盘写入100M数据")
foo("cpu去做其他事情")
'''
'''
#总消耗时长: 0.0010004043579101562
#创建线程实例
t1 = threading.Thread(target=foo,args=("磁盘写入100M数据",))
t2 = threading.Thread(target=foo,args=("cpu去做其他事情",))
#启动线程
t1.start()
t2.start()
'''
'''
#总消耗时长: 1.001000165939331
#创建线程实例
t1 = threading.Thread(target=foo,args=("磁盘写入100M数据",))
t2 = threading.Thread(target=foo,args=("cpu去做其他事情",))
#启动线程
t1.start()
t2.start()
#在子线程完成运行之前,这个子线程的主线程一直被阻塞
t1.join()
t2.join() #可以只有一个join
'''
end_time = time.time()
print("总消耗时长:",end_time-begin_time)
线程处理计算密集型任务
import threading
import time
def foo():
num = 0
for i in range(10000000):
num = num + i
begin_time = time.time()
'''
#串行 总消耗时长:1.819000005722046
foo()
foo()
'''
'''
#并发 总消耗时长:1.7979998588562012
t1 = threading.Thread(target=foo)
t2 = threading.Thread(target=foo)
t1.start()
t2.start()
t1.join()
t2.join()
'''
end_time = time.time()
print("总消耗时长:",end_time-begin_time)
join的功能
输出:
这是最后一行代码
3s后
阳光明媚
阻塞线程:
输出:
阳光明媚
3s后
这是最后一行代码
守护线程
import threading
import time
a = []
def foo():
while True:
a.append("1")
print("产生了一个数据")
time.sleep(1)
t = threading.Thread(target=foo)
#设置守护线程,必须在start之前
#作用就是在主线程想要提出进程的时候,不需要等待自己结束,直接退出就行
t.setDaemon(True)
t.start()
for i in range(5):
if a:
a.remove("1")
print("消耗了一个数据")
time.sleep(1)
print("不再需要消耗数据了")
输出:
不安全的开发
无锁:
import threading
import time
balance = 500 #账户余额
#操作账户余额
def foo(num):
#声明全局变量
global balance
#把接口获取到的值放进自己的变量系统
user_balance = balance
time.sleep(1) #防止代码太少,cpu执行速度过快,造成串行
#计算出结果
user_balance = user_balance + num
#将结果通过接口传递出去
balance = user_balance
#消费300元
t1 = threading.Thread(target=foo,args=[-300])
#收入10000元
t2 = threading.Thread(target=foo,args=[10000])
t1.start()
t2.start()
t1.join()
t2.join()
print("账户余额:",balance) #值不稳定,200或10500随机出现
上锁:
import threading
import time
balance = 500 #账户余额
r = threading.Lock() #声明一把锁
'''
这是一把同步锁
同步锁必须 上锁 解锁 相对
如果上锁后,不解锁,再次上锁,代码会阻塞
如果解锁后,不上锁,又进行解锁,代码会报错
'''
#操作账户余额
def foo(num):
#声明全局变量
global balance
#上锁
r.acquire()
#把接口获取到的值放进自己的变量系统
user_balance = balance
time.sleep(1) #防止代码太少,cpu执行速度过快,造成串行
#计算出结果
user_balance = user_balance + num
#将结果通过接口传递出去
balance = user_balance
#解锁
r.release()
#消费300元
t1 = threading.Thread(target=foo,args=[-300])
#收入10000元
t2 = threading.Thread(target=foo,args=[10000])
t1.start()
t2.start()
t1.join()
t2.join()
print("账户余额:",balance) #10200
死锁
import threading
import time
lockA = threading.Lock() #面试官的锁
lockB = threading.Lock() #小明的锁
#面试官
def foo1():
lockA.acquire() #上锁
print("请解释什么是死锁")
time.sleep(1)
lockB.acquire() #上锁
print("发 offer")
time.sleep(1)
lockA.release() #释放锁
lockB.release() #释放锁
#小明
def foo2():
lockB.acquire() # 上锁
print("请给我 offer")
time.sleep(1)
lockA.acquire() # 上锁
print("解释了什么是死锁")
time.sleep(1)
lockA.release() # 释放锁
lockB.release() # 释放锁
t1 = threading.Thread(target=foo1)
t2 = threading.Thread(target=foo2)
t1.start()
t2.start()
t1.join()
t2.join()
输出:
递归锁
import threading
import time
# lockA = threading.Lock() #面试官的锁
# lockB = threading.Lock() #小明的锁
lockR = threading.RLock() #递归锁
'''
递归锁内部维护着一把锁和一个计算器
每次上锁:计数器加1
每次解锁:计数器减1
计数器可以大于0,也可以等于0,但不能小于0
'''
#面试官
def foo1():
lockR.acquire() #上锁
print("请解释什么是死锁")
time.sleep(1)
lockR.acquire() #上锁
print("发 offer")
time.sleep(1)
lockR.release() #释放锁
lockR.release() #释放锁
#小明
def foo2():
lockR.acquire() # 上锁
print("请给我 offer")
time.sleep(1)
lockR.acquire() # 上锁
print("解释了什么是死锁")
time.sleep(1)
lockR.release() # 释放锁
lockR.release() # 释放锁
t1 = threading.Thread(target=foo1)
t2 = threading.Thread(target=foo2)
t1.start()
t2.start()
t1.join()
t2.join()
输出: