【问题标题】:variable locking in python thread fails to lock if multiple lock instance created?如果创建了多个锁实例,python线程中的变量锁定无法锁定?
【发布时间】:2019-04-13 20:57:10
【问题描述】:

我是线程新手,有一个问题..

from threading import Thread, Lock
s=0
lock =Lock()  ---->lock object position
def sample():
global s
for i in range(10000):
    lock.acquire()
    s+=1
    lock.release()    
t1 = Thread(target=sample)
t2 = Thread(target=sample)
t1.start()
t2.start()
t1.join()
t2.join()
print s

此代码给出 20000 的预期结果,因为对变量 s 的操作是原子完成的。

但是当我更改 lock() 创建位置时,锁没有按预期工作。我变了

 from threading import Thread, Lock
    s=0    
    def sample():
        lock =Lock()  ---> lock() added inside function
        global s
        for i in range(10000):
            lock.acquire()
            s+=1
            lock.release()    
    t1 = Thread(target=sample)
    t2 = Thread(target=sample)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print s

通过此更改,我得到了不一致的值。所以我猜测锁在这里不起作用。 有人可以根据这个例子帮助我理解锁的工作原理吗?
是否只有在两个线程都使用相同的锁定对象时才会兑现锁定?

TIA

【问题讨论】:

    标签: python multithreading


    【解决方案1】:

    在您的第一个版本中,锁是在线程启动之前创建的,并且是两个线程都可以使用的全局变量。因此,这个单一的锁对象在线程之间共享。锁对象一次只允许一个线程获取它。当它被获取时,调用.acquire() 的另一个线程将阻塞,直到另一个线程调用.release()。正如您所指出的,您的代码按预期工作。

    在您的第二个版本中,当您将 Lock 创建作为 局部变量 移动到线程函数中时。因此,每个线程调用sample 的不同运行,这会创建一个独特且不同的lock 对象。每个线程总是能够在不等待的情况下获取本地lock 变量,因为另一个线程总是在获取另一个锁。因此,s 变量并没有真正受到保护。

    【讨论】:

    • 但是两个锁都作用于单个变量's',并且无论调用者如何,变量都必须锁定? @selbie
    • 这样想。假设s 是一所房子。我们任何人都可以从前门进入房子并从里面锁上它。当我们离开房子时,我们让前门没有上锁。如果你的前门锁了,我不能进入它并改变房子里的家具布置 - 因为我们都引用同一个锁(前门上的那个)。但是如果我突然决定使用你家的后门,它使用不同的锁,我们可以同时在房子里。
    • 您的第一个版本类似于只有一扇门和锁的房子。你的第二个版本类似于每个人都有自己的门(用不同的锁)进入房子。
    • 在第二种情况下,我注意到输出只有很小的差异。如果我没有使用任何锁,我通常会得到大约 15000 而不是 20000 的值。但是当我使用错误的锁时,如第二个示例所示,我总是得到大约 19970 [只有大约 30 的差异]。我的意思是比较好的结果。所以在第二个例子中,我觉得变量不是 100% 不受保护的,就像没有锁的情况一样
    • 在不使用适当的锁定机制时,您会看到奇怪且不一致的结果的原因是因为每个线程都在本地缓存 s 的值,并将 s+1 的计算结果推迟回内存它想要。语言和硬件 CPU 线程优化都进行了假设另一个线程没有访问相同内存的优化。如果您想了解更多详细信息,请在 Google 上搜索“缓存一致性”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-15
    • 2021-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-01
    • 1970-01-01
    相关资源
    最近更新 更多