RLock vs Lock
轉(zhuǎn)載自:
https://blog.csdn.net/ybdesire/article/details/80294638
總結(jié):
Lock:該Lock只能被一個線程acquire一次,acquire后該Lock就處于Locked狀態(tài),必須release后才能被相同線程或其他的不同線程再次acquire一次。
RLock:該Lock可被同一線程多次acquire(如線程中含有遞歸或循環(huán)邏輯,遞歸或多次acquire該Lock),待該線程所有針對該Lock的acquire都被release后,才能被相同線程或其他的不同線程再次acquire。
首先講解不加鎖在多線程中會導(dǎo)致的問題,然后用實(shí)例說明如何通過加鎖讓函數(shù)變?yōu)榫€程安全的函數(shù)。也通過實(shí)例說明了RLock和Lock的區(qū)別:在同一線程內(nèi),對RLock進(jìn)行多次acquire()操作,程序不會阻塞。
threading.Lock的用法
下面是一個python多線程的例子:
import threading# global var
count = 0
# Define a function for the thread
def print_time(threadName):
global count
# Create and run threads as follows
try:
threading.Thread( target=print_time, args=(“Thread-1”, ) ).start()
threading.Thread( target=print_time, args=(“Thread-2”, ) ).start()
threading.Thread( target=print_time, args=(“Thread-3”, ) ).start()
except Exception as e:
print(“Error: unable to start thread”)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
在這個例子中,我們start了3個線程,每個線程都會對全局資源count進(jìn)行改寫操作。得到的結(jié)果如下,每個thread都會交替對count值進(jìn)行修改。
Thread-1: set count to 198 Thread-2: set count to 199 Thread-1: set count to 200 Thread-2: set count to 201 Thread-1: set count to 202 Thread-2: set count to 203 Thread-1: set count to 204 Thread-2: set count to 205- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
由于多線程共享進(jìn)程的資源和地址空間,因此,在對這些公共資源進(jìn)行操作時,為了防止這些公共資源出現(xiàn)異常的結(jié)果,必須考慮線程的同步和互斥問題。我們可以對上例中的print_time()中訪問資源的代碼加鎖,就可以把這個函數(shù)變?yōu)榫€程安全的函數(shù)。具體代碼如下:
import threading# global var
count = 0
lock = threading.Lock()
# Define a function for the thread
def print_time(threadName):
global count
# Create and run threads as follows
try:
threading.Thread( target=print_time, args=(“Thread-1”, ) ).start()
threading.Thread( target=print_time, args=(“Thread-2”, ) ).start()
threading.Thread( target=print_time, args=(“Thread-3”, ) ).start()
except Exception as e:
print(“Error: unable to start thread”)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
通過threading.Lock(),就能實(shí)現(xiàn)加鎖。這樣每個thread對count進(jìn)行改動期間,就不會有其它的thread插入進(jìn)來改動count。得到的輸出如下:
Thread-2: set count to 199 Thread-2: set count to 200 Thread-3: set count to 201 Thread-3: set count to 202 Thread-3: set count to 203 Thread-3: set count to 204- 1
- 2
- 3
- 4
- 5
- 6
鎖的使用,有兩種方法,上面的是最簡單的通過with lock來操作。
還有另一種用法,是通過Lock的acquire()和release()函數(shù)來控制加鎖和解鎖,如下例,得到的結(jié)果和上例相同:
import threading# global var
count = 0
lock = threading.Lock()
# Define a function for the thread
def print_time(threadName):
global count
# Create and run threads as follows
try:
threading.Thread( target=print_time, args=(“Thread-1”, ) ).start()
threading.Thread( target=print_time, args=(“Thread-2”, ) ).start()
threading.Thread( target=print_time, args=(“Thread-3”, ) ).start()
except Exception as e:
print(“Error: unable to start thread”)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
Lock與RLock的區(qū)別
上例中,我們使用threading.Lock()來進(jìn)行加鎖。threading中還提供了另外一個threading.RLock(),那么問題來了,Lock與RLock有什么區(qū)別呢?
既然要討論區(qū)別,那我們應(yīng)該明白,他們的功能,大部分是相同的,很多情況下可以通用,但有細(xì)微的區(qū)別。
從原理上來說:在同一線程內(nèi),對RLock進(jìn)行多次acquire()操作,程序不會阻塞。
用一個例子來說明:
import threadinglock = threading.RLock()
def f():
with lock:
g()
h()
def g():
with lock:
h()
do_something1()
def h():
with lock:
do_something2()
def do_something1():
print(‘do_something1’)
def do_something2():
print(‘do_something2’)
# Create and run threads as follows
try:
threading.Thread( target=f ).start()
threading.Thread( target=f ).start()
threading.Thread( target=f ).start()
except Exception as e:
print(“Error: unable to start thread”)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
每個thread都運(yùn)行f(),f()獲取鎖后,運(yùn)行g(shù)(),但g()中也需要獲取同一個鎖。如果用Lock,這里多次獲取鎖,就發(fā)生了死鎖。
但我們代碼中使用了RLock。在同一線程內(nèi),對RLock進(jìn)行多次acquire()操作,程序不會堵塞,所以我們可以得到如下的輸出:
總結(jié)
以上是生活随笔為你收集整理的RLock vs Lock的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 新录制了一个Cytoscape整合富集分
- 下一篇: 【转】提纲挈领webrtc之NS(noi