What is a lock mechanism ?
Lock() Manage threads
RLock() And Lock() The difference between
What is a lock mechanism ?Answer that question , We need to know why we need to use the locking mechanism . We mentioned earlier that some resources of multiple threads in a process are shared , This is also a major advantage of threads , But it also brings a problem , That is, when two or more threads access shared resources at the same time , If there is no preset synchronization mechanism , It may lead to multiple threads accessing the same shared resource at the same time , That is, there is competition , In most cases, we don't want this to happen , So how to avoid it ?
Lock() Manage threadsLet's start with a piece of code :
import threadingimport timeresource = 0count = 1000000resource_lock = threading.Lock()def increment(): global resource for i in range(count): resource += 1def decerment(): global resource for i in range(count): resource -= 1increment_thread = threading.Thread(target=increment)decerment_thread = threading.Thread(target=decerment)increment_thread.start()decerment_thread.start()increment_thread.join()decerment_thread.join()print(resource)
The running screenshot is as follows :
Running results
When we run many times , We can see that the final result is almost not equal to the value we expect, that is resource
Initial value 0
.
Why? ? The reason is because += and -= It's not an atomic operation .
have access to dis Module view bytecode :
import disdef add(total): total += 1def desc(total): total -= 1total = 0print(dis.dis(add))print(dis.dis(desc))# Running results :# 3 0 LOAD_FAST 0 (total)# 3 LOAD_CONST 1 (1)# 6 INPLACE_ADD# 7 STORE_FAST 0 (total)# 10 LOAD_CONST 0 (None)# 13 RETURN_VALUE# None# 5 0 LOAD_FAST 0 (total)# 3 LOAD_CONST 1 (1)# 6 INPLACE_SUBTRACT# 7 STORE_FAST 0 (total)# 10 LOAD_CONST 0 (None)# 13 RETURN_VALUE# None
So how to ensure that the initial value is 0
Well ? We can use Lock()
, The code is as follows :
import threadingimport timeresource = 0count = 1000000resource_lock = threading.Lock()def increment(): global resource for i in range(count): resource_lock.acquire() resource += 1 resource_lock.release()def decerment(): global resource for i in range(count): resource_lock.acquire() resource -= 1 resource_lock.release()increment_thread = threading.Thread(target=increment)decerment_thread = threading.Thread(target=decerment)increment_thread.start()decerment_thread.start()increment_thread.join()decerment_thread.join()print(resource)
The running screenshot is as follows :
Running results
From the running results, we can see that , No matter how many times we run the code , Its resource
All values of are initial values 0
, This is it. Lock()
Credit , That is, it can restrict access to a single thread or a single type of thread at a certain time , When accessing locked shared resources , You must obtain the corresponding lock now to access , That is, wait for other threads to release resources , namely resource_lock.release()
Of course, in order to prevent us from locking a resource , Forget to release the lock , Lead to a deadlock , We can use the context manager to manage locks to achieve the same effect :
import threadingimport timeresource = 0count = 1000000resource_lock = threading.Lock()def increment(): global resource for i in range(count): with resource_lock: resource += 1def decerment(): global resource for i in range(count): with resource_lock: resource -= 1increment_thread = threading.Thread(target=increment)decerment_thread = threading.Thread(target=decerment)increment_thread.start()decerment_thread.start()
RLock() And Lock() The difference between We need to know Lock()
As a basic lock object , Only one lock at a time , Other lock requests , Wait for the lock to release before obtaining , Otherwise, deadlock will occur :
import threadingresource.lock = threading.lock()resource = 0resource.lock.acquire()resource.lock.acquire()resource += 1resource.lock.release()resource.lock.release()
To solve the problem that the same resource cannot be requested multiple times in the same thread ,python Provides “ Reentrant lock ”:threading.RLock
,RLock
One is maintained internally Lock
And a counter
Variable ,counter
Recorded acquire
The number of times , So that the resource can be multiple times acquire
.
All the way to a thread acquire
All be release
, Only other threads can get the resource . Usage and threading.Lock
Similar classes , For example, the use of recursive locks :
import threadinglock = threading.RLock()def dosomething(lock): lock.acquire() # do something lock.release()lock.acquire()dosomething(lock)lock.release()
That's all Python Parallel programming multithread locking mechanism Lock And RLock Details of thread synchronization , More about Python lock Lock RLock For thread synchronization information, please pay attention to other related articles on the software development network !