前言
- 当多个线程操作同一数据时,会导致该数据出现的不是正确的值
- 所以出现了线程锁,即同一时刻只允许一个线程执行操作,这样可以确保数据的准确性
示例代码
import threading
import time
num = 0
tname = lambda: threading.currentThread().name
def task():
print(f"线程开始... ({tname()})")
global num
for j in range(10_0000):
num += 1
print(f"线程结束... ({tname()})")
def main():
t1 = time.time()
ts = []
for j in range(10):
t = threading.Thread(target=task)
ts.append(t)
for t in ts:
t.start()
for t in ts:
t.join()
print(f"num: {num}")
print(f"耗时: {time.time() - t1}")
if __name__ == '__main__':
main()
- 上方代码中,总共有10个线程对全局变量num进行操作,每个线程都是把num的值增加10w
- 所以当所有线程结束后,num正确的值应为 10 × 10w = 100w
代码运行
- 结果并不是100w
- 因为线程并没有上锁
- 运行结束总共耗时0.1s,记住这个时间,后面会说到
上锁
import threading
import time
num = 0
lock = threading.Lock()
tname = lambda: threading.currentThread().name
def task():
print(f"线程开始... ({tname()})")
global num
for j in range(10_0000):
lock.acquire()
num += 1
lock.release()
print(f"线程结束... ({tname()})")
def main():
t1 = time.time()
ts = []
for j in range(10):
t = threading.Thread(target=task)
ts.append(t)
for t in ts:
t.start()
for t in ts:
t.join()
print(f"num: {num}")
print(f"耗时: {time.time() - t1}")
if __name__ == '__main__':
main()
- 不难看出,只是在操作num的上下加了获取锁、释放锁这两句代码
- 因为之前就是在同一时刻,有多个线程操作num的值,所以最后num的值才会不准确
代码运行
- 可以看到最后num的值是准确的100w
- 运行结束总共耗时3s,因为上锁的时候,同一时刻只能有一个线程执行,所以其他线程在等待锁的释放,这里消耗了时间,所以时间比之前的不上锁(耗时0.1s)耗费的时间长