程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python 線程中控制資源的訪問

編輯: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 元

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved