2012-05-09 120 views
33

我想了解線程和併發的基礎知識。我想要一個簡單的例子,其中兩個線程反覆嘗試訪問一個共享資源。Python線程。我如何鎖定線程?

代碼:

import threading 

class Thread(threading.Thread): 
    def __init__(self, t, *args): 
     threading.Thread.__init__(self, target=t, args=args) 
     self.start() 
count = 0 
lock = threading.Lock() 

def incre(): 
    global count 
    lock.acquire() 
    try: 
     count += 1  
    finally: 
     lock.release() 

def bye(): 
    while True: 
     incre() 

def hello_there(): 
    while True: 
     incre() 

def main():  
    hello = Thread(hello_there) 
    goodbye = Thread(bye) 

    while True: 
     print count 

if __name__ == '__main__': 
    main() 

所以,我有兩個線程,都試圖增加計數器。我認爲如果線程'A'調用incre()lock將被建立,阻止'B'訪問直到'A'發佈。

運行表明事實並非如此。您可以獲得所有隨機數據比賽增量。

鎖對象究竟是如何使用的?

編輯另外,我已經嘗試把鎖定在線程函數內,但仍然沒有運氣。

+0

你的代碼不能運行。 –

+0

@Ignacio Vazquez-Abrams - 現在應該。我遺漏了'if __name__'位。那是你所指的? – Zack

+1

它也不適合我。我希望你的線程創建看起來像:'hello = threading.Thread(target = hello_there)',然後爲線程啓動'hello.start()'。 –

回答

40

如果您放慢進程並讓它們更多地阻塞,您可以看到您的鎖正在使用它們,正如您正在使用它們一樣。你有正確的想法,在那裏你用鎖來圍繞關鍵代碼段。以下是對示例的一個小調整,以向您展示每個人如何等待另一個人釋放鎖。

import threading 
import time 
import inspect 

class Thread(threading.Thread): 
    def __init__(self, t, *args): 
     threading.Thread.__init__(self, target=t, args=args) 
     self.start() 

count = 0 
lock = threading.Lock() 

def incre(): 
    global count 
    caller = inspect.getouterframes(inspect.currentframe())[1][3] 
    print "Inside %s()" % caller 
    print "Acquiring lock" 
    with lock: 
     print "Lock Acquired" 
     count += 1 
     time.sleep(2) 

def bye(): 
    while count < 5: 
     incre() 

def hello_there(): 
    while count < 5: 
     incre() 

def main():  
    hello = Thread(hello_there) 
    goodbye = Thread(bye) 


if __name__ == '__main__': 
    main() 

輸出示例:

... 
Inside hello_there() 
Acquiring lock 
Lock Acquired 
Inside bye() 
Acquiring lock 
Lock Acquired 
... 
+0

哦,整潔!我想我被'main()'中的'print count'弄糊塗了,顯示出不穩定的迭代。但我想這是因爲我有三個循環同時運行。謝謝!還有關於檢查模塊的TIL。很酷。 – Zack

+0

@Zack:Ya我認爲這是主打印讓你困惑。它沒有限制,所以它的打印速度比線程甚至改變它要快。 – jdi

+0

@jdi我試圖理解鎖定,所以我加了一個打印(計數)到您的增量功能後計數+ = 1,但是當我運行代碼時,它得到6? – ErinGoBragh