詳解python中的Lock與RLock

2021-08-19 22:10:02 字數 4867 閱讀 7011

首先講解不加鎖在多執行緒中會導致的問題,然後用例項說明如何通過加鎖讓函式變為執行緒安全的函式。也通過例項說明了rlocklock的區別:在同一執行緒內,對rlock進行多次acquire()操作,程式不會阻塞。

下面是乙個python多執行緒的例子:

import threading

# global var

count = 0

# define a function for the thread

defprint_time

(threadname):

global count

c=0while(c<100):

c+=1

count+=1

print(": set count to ".format( threadname, 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")

在這個例子中,我們start了3個執行緒,每個執行緒都會對全域性資源count進行改寫操作。得到的結果如下,每個thread都會交替對count值進行修改。

thread-1: set

count

to198

thread-2: set

count

to199

thread-1: set

count

to200

thread-2: set

count

to201

thread-1: set

count

to202

thread-2: set

count

to203

thread-1: set

count

to204

thread-2: set

count

to205

由於多執行緒共享程序的資源和位址空間,因此,在對這些公共資源進行操作時,為了防止這些公共資源出現異常的結果,必須考慮執行緒的同步和互斥問題。我們可以對上例中的print_time()中訪問資源的**加鎖,就可以把這個函式變為執行緒安全的函式。具體**如下:

import threading

# global var

count = 0

lock = threading.lock()

# define a function for the thread

defprint_time

(threadname):

global count

c=0with lock:

while(c<100):

c+=1

count+=1

print(": set count to ".format( threadname, 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")

通過threading.lock(),就能實現加鎖。這樣每個thread對count進行改動期間,就不會有其它的thread插入進來改動count。得到的輸出如下:

thread-2: set

count

to199

thread-2: set

count

to200

thread-3: set

count

to201

thread-3: set

count

to202

thread-3: set

count

to203

thread-3: set

count

to204

鎖的使用,有兩種方法,上面的是最簡單的通過with lock來操作。

還有另一種用法,是通過lock的acquire()release()函式來控制加鎖和解鎖,如下例,得到的結果和上例相同:

import threading

# global var

count = 0

lock = threading.lock()

# define a function for the thread

defprint_time

(threadname):

global count

c=0if(lock.acquire()):

while(c<100):

c+=1

count+=1

print(": set count to ".format( threadname, count) )

lock.release()

# 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")

上例中,我們使用threading.lock()來進行加鎖。threading中還提供了另外乙個threading.rlock(),那麼問題來了,lockrlock有什麼區別呢?

既然要討論區別,那我們應該明白,他們的功能,大部分是相同的,很多情況下可以通用,但有細微的區別。

從原理上來說:在同一執行緒內,對rlock進行多次acquire()操作,程式不會阻塞。

用乙個例子來說明:

import threading

lock = threading.rlock()

deff

():with lock:

g()h()

defg

():with lock:

h()do_something1()

defh

():with lock:

do_something2()

defdo_something1

(): print('do_something1')

defdo_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")

每個thread都執行f()f()獲取鎖後,執行g(),但g()中也需要獲取同乙個鎖。如果用lock,這裡多次獲取鎖,就發生了死鎖。

但我們**中使用了rlock。在同一執行緒內,對rlock進行多次acquire()操作,程式不會堵塞,所以我們可以得到如下的輸出:

do_something2

do_something1

do_something2

do_something2

do_something1

do_something2

do_something2

do_something1

do_something2

C 中lock用法詳解

lock 關鍵字可以用來確保 塊完成執行,而不會被其他執行緒中斷。這是通過在 塊執行期間為給定物件獲取互斥鎖來實現的。先來看看執行過程,示例如下 lock 語句用於獲取某個給定物件的互斥鎖,執行乙個語句,然後釋放該鎖。lock statement lock 語句 複製 如下 lock express...

python多執行緒中Lock 與RLock 鎖

資源總是有限的,程式執行如果對同乙個物件進行操作,則有可能造成資源的爭用,甚至導致死鎖 也可能導致讀寫混亂 鎖提供如下方法 1.lock.acquire blocking 2.lock.release 3.threading.lock 載入執行緒的鎖物件,是乙個基本的鎖物件,一次只能乙個鎖定,其餘鎖...

python執行緒中的執行緒鎖Lock物件

原語鎖定 或互斥鎖定 是乙個同步原語,狀態是 已鎖定 或者 未鎖定 之一。兩個方法 acquire 和 release 用於修改鎖定的狀態。如果狀態已鎖定,嘗試獲取鎖定將被阻塞,直到鎖定被釋放為止。如果有多個執行緒等待獲取鎖定,當鎖定釋放時,只有乙個執行緒能獲得它。等待執行緒獲得鎖定的順序沒有定義。...