2016-11-30 118 views
1

Python 3.x都有鎖是否需要聲明爲全局?

import threading 

lock = threading.Lock() 
counter = 0 

def update_counter(): 
    global counter 

    lock.acquire() 
    counter += 1 
    lock.release() 

# starts threads, target update_counter 

是否鎖必須是全球性的?如果不是,由於未定義本地鎖定,它不會導致錯誤?

謝謝

+0

試用時是否遇到錯誤? – Evert

+0

附註:不要手動調用'acquire'和'release'。儘可能使用'with'語句;它是例外的安全的,並且避免了忘記正確匹配'acquire'和'release'的可能性。 – ShadowRanger

回答

1

直接回答這個問題,那counter需要聲明globallock不會是因爲你重新分配到counter(與counter += 1)的原因,而你只在lock調用方法。對於一個變量的引用,如果沒有局部變量存在,Python會查找封閉範圍直到它找到一個匹配。在這種情況下,它會在全局範圍內找到它。對於變量的賦值,Python將假定該變量是本地的,除非另有明確聲明(使用globalnonlocal)。

0

鎖保護一些資源,並且通常與資源的範圍相同。在你的情況下,你正在保護一個全局計數器,所以鎖定也必須是全局的。所有訪問資源的線程都必須使用相同的鎖,因此在函數本身中創建私有鎖是沒有用的 - 沒有其他線程會看到它。

某些應用程序使用單個鎖來保護所有共享資源(粒度鎖定)。但是你也可以鎖定數據(細粒度鎖定)。細粒度鎖定的一個實例是:

class MyCounter: 

    def __init__(self): 
     self.lock = threading.Lock() 
     self.value = 0 

    def increment(self): 
     with self.lock: 
      self.value += 1 

現在,MyCounter每個實例具有鎖定和獨立運行。

+0

似乎並不pythonic – df86

+0

什麼似乎pythonic?在你的例子中,'lock'應該是全局的,就像你寫的那樣,因爲你所保護的資源是全局的。所有使用該資源的代碼都需要獲取1個鎖才能工作。 – tdelaney

+0

您也可以在函數中聲明'全局鎖定'並在本地命名空間中保存額外的查找。但一般來說,如果您不重新綁定變量,則不需要'global'關鍵字。 – tdelaney