首先講解不加鎖在多執行緒中會導致的問題,然後用例項說明如何通過加鎖讓函式變為執行緒安全的函式。也通過例項說明了rlock
和lock
的區別:在同一執行緒內,對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()
,那麼問題來了,lock
與rlock
有什麼區別呢?
既然要討論區別,那我們應該明白,他們的功能,大部分是相同的,很多情況下可以通用,但有細微的區別。
從原理上來說:在同一執行緒內,對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 用於修改鎖定的狀態。如果狀態已鎖定,嘗試獲取鎖定將被阻塞,直到鎖定被釋放為止。如果有多個執行緒等待獲取鎖定,當鎖定釋放時,只有乙個執行緒能獲得它。等待執行緒獲得鎖定的順序沒有定義。...