Python 3.x 锁是否需要声明为全局锁?

Python 3.x 锁是否需要声明为全局锁?,python-3.x,Python 3.x,Python3.x import threading lock = threading.Lock() counter = 0 def update_counter(): global counter lock.acquire() counter += 1 lock.release() # starts threads, target update_counter 锁也必须是全局的吗?如果没有,由于未定义本地锁,它如何不导致错误 谢谢锁保护某些资源,并且通

Python3.x

import threading

lock = threading.Lock()
counter = 0

def update_counter():
    global counter

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

# starts threads, target update_counter
锁也必须是全局的吗?如果没有,由于未定义本地锁,它如何不导致错误


谢谢

锁保护某些资源,并且通常与资源的作用域相同。在您的情况下,您正在保护一个全局计数器,因此锁也必须是全局的。所有访问该资源的线程都必须使用相同的锁,因此在函数本身中创建私有锁不会有任何好处——其他线程都不会看到它

有些应用程序使用单个锁来保护所有共享资源(当然是细粒度锁)。但您也可以对数据保持锁定(细粒度锁定)。细粒度锁定的一个示例是:

class MyCounter:

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

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

现在,
MyCounter
的每个实例都有一个锁并独立运行。

要直接回答这个问题,需要声明
counter
全局
,而
lock
不需要声明的原因是您正在重新分配给
counter
(使用
counter+=1
)而您只在
lock
上调用方法。对于变量的引用,如果不存在局部变量,Python将在封闭范围内查找,直到找到匹配项为止。在本例中,它在全局范围内找到它。对于变量赋值,Python将假定变量为本地变量,除非明确声明为其他变量(使用
global
nonlocal
)。

尝试时是否遇到错误?旁注:不要手动调用
acquire
release
。尽可能使用带有
语句的
;它是异常安全的,避免了忘记正确匹配
acquire
release
调用的可能性?在您的示例中,
lock
应该是全局的,就像您编写的一样,因为您保护的资源是全局的。使用该资源的所有代码都需要获取1锁才能工作。如果需要,还可以在函数中声明
全局锁
,并在本地命名空间中保存额外的查找。但通常,如果不重新绑定变量,则不需要
global
关键字。