Python -- 线程安全问题


前言

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

示例代码

# -*- 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)耗费的时间长
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值