Python 线程中控制资源的访问

文章目录

前言

在多线程场景中,除了同步线程操作,还有一点很重要,那就是要能够控制对共享资源的访问,从而避免破坏或丢失数据。Python的内置数据结构(列表、字典等)是线程安全的, 这是Python使用原子字节码来管理这些数据结构的一个副作用(更新数据结构过程中不会释放GIL)。而Python中其他数据结构或更简单的类型则没有这个保护。要安全的访问一个对象,可以使用Lock对象。
假设这样一个场景:两个人同时在一个银行账户取钱,余额不足是取不出来的,如果不对账户余额(共享资源)进行访问控制,会出现什么情况呢?看下边的代码示例

代码展示

没有对余额进行访问控制的情况

import time
import logging
from threading import Thread, Barrier, Lock

logging.basicConfig(level=logging.DEBUG, format='%(threadName)s-%(asctime)s-%(message)s')


class Account:

    def __init__(self):
        self.balance = 100  # 余额

    def get_money(self, v):
        if self.balance >= v:
            logging.debug('正在出钞:%d 元,请稍后...', v)
            time.sleep(1)
            self.balance -= v
            logging.debug('余额:%d 元', self.balance)
        else:
            logging.debug('余额不足:%d 元', self.balance)


def get_money(b: Account, v: int):
    b.get_money(v)


if __name__ == '__main__':
    b = Account()
    t1 = Thread(target=get_money, args=(b, 50))
    t2 = Thread(target=get_money, args=(b, 60))
    t1.start()
    t2.start()

余额总共100元,线程1取50, 线程2取60, 结果:

Thread-1-2022-06-27 11:10:34,009-正在出钞:50 元,请稍后...
Thread-2-2022-06-27 11:10:34,010-正在出钞:60 元,请稍后...
Thread-2-2022-06-27 11:10:35,024-余额:40 元
Thread-1-2022-06-27 11:10:35,024-余额:-10 元

很明显,这并不是我们期望看到的结果。我们需要对余额进行访问控制,保证同一时刻只有一个线程对余额进行修改
对余额进行访问控制的情况

def get_money(self, v):
    self.lock.acquire()
    if self.balance >= v:
        logging.debug('正在出钞:%d 元,请稍后...', v)
        time.sleep(1)
        self.balance -= v
        logging.debug('余额:%d 元', self.balance)
    else:
        logging.debug('余额不足:%d 元', self.balance)
    self.lock.release()

结果如下,符合我们的预期

Thread-1-2022-06-27 11:29:14,400-正在出钞:50 元,请稍后...
Thread-1-2022-06-27 11:29:15,403-余额:50 元
Thread-2-2022-06-27 11:29:15,403-余额不足:账户只有 50
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值