In a multithreaded scenario , In addition to synchronous thread operations , Another important point , That is to be able to control access to shared resources , To avoid data corruption or loss .Python Built in data structure ( list 、 Dictionary, etc ) It's thread safe , This is a Python One side effect of using atomic bytecode to manage these data structures ( The data structure will not be released during update GIL). and Python Other data structures or simpler types in the do not have this protection . To access an object safely , have access to Lock object .
Suppose such a scenario : Two people withdraw money from the same bank account at the same time , If the balance is insufficient, you cannot withdraw it , If the account balance is not ( Shared resources ) Access control , What will happen ? Look at the code example below
There is no access control on the balance
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 # balance
def get_money(self, v):
if self.balance >= v:
logging.debug(' Issuing cash :%d element , Please later ...', v)
time.sleep(1)
self.balance -= v
logging.debug(' balance :%d element ', self.balance)
else:
logging.debug(' Lack of balance :%d element ', 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()
The balance totals 100 element , Threads 1 take 50, Threads 2 take 60, result :
Thread-1-2022-06-27 11:10:34,009- Issuing cash :50 element , Please later ...
Thread-2-2022-06-27 11:10:34,010- Issuing cash :60 element , Please later ...
Thread-2-2022-06-27 11:10:35,024- balance :40 element
Thread-1-2022-06-27 11:10:35,024- balance :-10 element
Obviously , This is not what we expected to see . We need access control for the balance , Ensure that only one thread can modify the balance at the same time Access control of balances
def get_money(self, v):
self.lock.acquire()
if self.balance >= v:
logging.debug(' Issuing cash :%d element , Please later ...', v)
time.sleep(1)
self.balance -= v
logging.debug(' balance :%d element ', self.balance)
else:
logging.debug(' Lack of balance :%d element ', self.balance)
self.lock.release()
give the result as follows , In line with our expectations
Thread-1-2022-06-27 11:29:14,400- Issuing cash :50 element , Please later ...
Thread-1-2022-06-27 11:29:15,403- balance :50 element
Thread-2-2022-06-27 11:29:15,403- Lack of balance : The account has only 50 element