前言

  • 当多个线程操作同一数据时,会导致该数据出现的不是正确的值
  • 所以出现了线程锁,即同一时刻只允许一个线程执行操作,这样可以确保数据的准确性

示例代码

# -*- coding: utf-8 -*-
# @Author   : zbz

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,记住这个时间,后面会说到

上锁

# @Time    : 2021/6/16 9:26

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)耗费的时间长
Logo

为开发者提供按需使用的算力基础设施。

更多推荐