python并发编程笔记4

本文介绍了Python并发编程中线程安全的概念,通过实例展示了线程不安全可能导致的问题,并详细讲解了如何使用Lock进行解决。通过try-finally和with模式两种方式演示了Lock的使用,以确保在多线程环境下正确处理共享变量,避免出现取钱操作等并发问题。
摘要由CSDN通过智能技术生成

python并发编程笔记4

是根据蚂蚁学Python的视频做的笔记,方便自己后续回顾

视频链接:BV1bK411A7tV

老师的源码

这一份笔记对应的是视频的P6

P6-Python线程安全问题以及解决方案

1、线程安全概念介绍

线程安全:指某个函数、函数库在多线程环境中被调用时,能够正确地处理多个线程之间的共享变量,使程序功能正确完成。

线程不安全:由于线程的执行随时会发生切换,就造成了不可预料的结果,出现线程不安全

如下图:i代码是没有问题的,但如果if语句判断完,发生线程切换,就会造成错误

在这里插入图片描述

2、Lock用于解决线程安全问题

2.1、try-finally模式

import threading

# 获取lock对象
lock = threading.Lock()

# 获取这个锁
lock.acquire()
try:
    # do something
finally:
    # 释放锁
    lock.release()

2.2、with模式

import threading

lock = threading.Lock()

with# do something

把代码放到lock里面,就不会出现上述提到的取钱扣多钱的问题

3、实例代码演示问题以及解决方案

3.1、随机可能出错版本:

# 03lock_concurrent.py

import threading


# 创建一个账号类
class Account:
    def __init__(self, balance):
        self.balance = balance


# 取钱函数
def draw(account, amount):
    if account.balance >= amount:
        print(threading.current_thread().name,
              "取钱成功")
        account.balance -= amount
        print(threading.current_thread().name,
              "余额", account.balance)
    else:
        print(threading.current_thread().name,
              "取钱失败,余额不足")


if __name__ == '__main__':
    # 实例账号对象,1000元进账户
    account = Account(1000)
    # 实例俩个线程对象
    ta = threading.Thread(name="ta", target=draw, args=(account, 800))
    tb = threading.Thread(name="tb", target=draw, args=(account, 800))
    # 启动两个线程对象
    ta.start()
    tb.start()

3.2、一定出问题(添加sleep语句):

sleep语句一定会导致当前线程阻塞,阻塞就会切换线程

# 03lock_concurrent.py

import threading
import time


# 创建一个账号类
class Account:
    def __init__(self, balance):
        self.balance = balance


# 取钱函数
def draw(account, amount):
    if account.balance >= amount:
        # sleep语句一定会导致当前线程阻塞,阻塞就会切换线程
        time.sleep(0.1)
        print(threading.current_thread().name,
              "取钱成功")
        account.balance -= amount
        print(threading.current_thread().name,
              "余额", account.balance)
    else:
        print(threading.current_thread().name,
              "取钱失败,余额不足")


if __name__ == '__main__':
    # 实例账号对象,1000元进账户
    account = Account(1000)
    # 实例俩个线程对象
    ta = threading.Thread(name="ta", target=draw, args=(account, 800))
    tb = threading.Thread(name="tb", target=draw, args=(account, 800))
    # 启动两个线程对象
    ta.start()
    tb.start()

3.3、解决方案:with模式

在类上添加lock = threading.Lock(),并将draw函数嵌入with中

# 03lock_concurrent.py

import threading
import time

lock = threading.Lock()


# 创建一个账号类
class Account:
    def __init__(self, balance):
        self.balance = balance


# 取钱函数
def draw(account, amount):
    with lock:
        if account.balance >= amount:
            # sleep语句一定会导致当前线程阻塞,阻塞就会切换线程
            time.sleep(0.1)
            print(threading.current_thread().name,
                  "取钱成功")
            account.balance -= amount
            print(threading.current_thread().name,
                  "余额", account.balance)
        else:
            print(threading.current_thread().name,
                  "取钱失败,余额不足")


if __name__ == '__main__':
    # 实例账号对象,1000元进账户
    account = Account(1000)
    # 实例俩个线程对象
    ta = threading.Thread(name="ta", target=draw, args=(account, 800))
    tb = threading.Thread(name="tb", target=draw, args=(account, 800))
    # 启动两个线程对象
    ta.start()
    tb.start()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值