无锁多线程案例
import threading
import time
num = 100
def fun_sub():
global num
num2 = num
time.sleep(0.001)
num = num2 - 1
if __name__ == '__main__':
print('开始测试同步锁 at %s' % time.ctime())
thread_list = []
for thread in range(100):
t = threading.Thread(target=fun_sub)
t.start()
thread_list.append(t)
for t in thread_list:
t.join()
print(f"num is {num}")
print(f"结束测试同步锁 at {time.ctime()}")
通过 100 个线程分别调用 fun_sub() 函数来修改公共变量 num,会产生当某线程在 time.sleep(0.001) 挂起时,其之后的线程 num2 = num 并没有拿到该线程的结果 num 值 进行错位运算,导致最终误差:
开始测试同步锁 at Fri Aug 14 18:34:15 2020
num is 94
结束测试同步锁 at Fri Aug 14 18:34:15 2020
理论上 100 个线程对 num 先后 -1 结果应该是 0 的。
为线程添加同步锁
同步锁的作用是只允许一个线程来操作共享资源:
import threading
import time
num = 100
def fun_sub():
global num
lock.acquire()
print("-----加锁-----")
print("现在操作共享资源的线程名字是:", t.name)
num2 = num
time.sleep(0.001)
num = num2 - 1
lock.release()
print("-----释放锁-----")
if __name__ == '__main__':
print('开始测试同步锁 at %s' % time.ctime())
lock = threading.Lock()
thread_list = []
for thread in range(100):
t = threading.Thread(target=fun_sub)
t.start()
thread_list.append(t)
for t in thread_list:
t.join()
print(f"num is {num}")
print(f"结束测试同步锁 at {time.ctime()}")
注意加了锁之后,只允许单线程来访问共享数据,那么多线程意义在哪呢?注意锁的作用对象是共享数据,但多线程并非时刻都在访问共享数据,所以我们要把锁加在特定共享数据处,以减小对多线程代码的副作用影响。