01、线程不安全举例
import threading
total = 0
def add():
global total
for i in range(1000000):
total = total + 1
def desc():
global total
for i in range(1000000):
total = total - 1
thread_01 = threading.Thread(target=add)
thread_02 = threading.Thread(target=desc)
thread_01.start()
thread_02.start()
thread_01.join()
thread_02.join()
print(total)
****** 执行结果 ******
可能为 0~2000000 之间任意一个值,例如1356812
02、通过字节码分析一下为什么线程数据不同步
import dis
def add(a):
a += 1
def desc(a):
a -= 1
print(dis.dis(add))
print(dis.dis(desc))
************** 字节码结果如下 **************
5 0 LOAD_FAST 0 (a) -- 加载变量 a = 0
2 LOAD_CONST 1 (1) -- 加载常量 1
4 INPLACE_ADD -- 执行 + 操作 a = a+1
6 STORE_FAST 0 (a) -- 存储数据给a a = 1
8 LOAD_CONST 0 (None)
10 RETURN_VALUE
None
8 0 LOAD_FAST 0 (a) -- 加载变量 a = 0
2 LOAD_CONST 1 (1) -- 加载常量 1
4 INPLACE_SUBTRACT -- 执行 - 操作 a = a-1
6 STORE_FAST 0 (a) -- 存储数据给a a= -1
8 LOAD_CONST 0 (None)
10 RETURN_VALUE
None
03、python提供了几种线程同步机制 【也就是几种锁机制】
--加锁:让一个时间段只有一个代码段||对象在运行或被操作
--导入模块:from threading import Lock
--锁的声明:lock = Lock()
--获得锁:lock.acquire()
--释放锁:lock.release()
--锁的使用缺点:
--性能降低
-死锁:
--常见的四个条件:
--
--
--
--
--常见死锁代码示例:
--01、执行的需要的资源相互依存
A 锁 锁住C资源,同时需要D资源
B 锁 锁住D资源,同时需要C资源
两个锁的执行都依赖于对方的执行结束
--02、同一把锁嵌套
--针对上面同一把锁嵌套问题,我们可以使用嵌套锁进行解决
--RLock:可重入的锁,方法和Lock基本一致
--加锁的代码示例:这里不再使用global,而是传参的方式。因为python中传递的就是参数的引用
--记住锁的使用会导致性能降低
import threading
from threading import Lock
def add(total, lock):
for i in range(1000000):
lock.acquire()
total = total + 1
lock.release()
def desc(total, lock):
for i in range(1000000):
lock.acquire()
total = total - 1
lock.release()
total = 0
lock = Lock()
thread_01 = threading.Thread(target=add, args=(total, lock))
thread_02 = threading.Thread(target=desc, args=(total, lock))
thread_01.start()
thread_02.start()
thread_01.join()
thread_02.join()
print(total)
--RLock:可重入的锁的代码示例:
import threading
from threading import Lock, RLock
def add(total, lock):
for i in range(1000000):
lock.acquire()
lock.acquire()
total = total + 1
lock.release()
lock.release()
def desc(total, lock):
for i in range(1000000):
lock.acquire()
lock.acquire()
total = total - 1
lock.release()
lock.release()
total = 0
lock = RLock()
thread_01 = threading.Thread(target=add, args=(total, lock))
thread_02 = threading.Thread(target=desc, args=(total, lock))
thread_01.start()
thread_02.start()
thread_01.join()
thread_02.join()
print(total)