python threading.Lock() 是否锁定所有需要锁定的东西?

uho*_*hoh 5 python python-multithreading python-2.7

下面的脚本是抽象的。我的问题是关于使用threading.Lock()

锁定限制了对“共享资源”的访问,但我对这能走多远感到紧张。我有对象属性,它们是在这个例子中具有数组属性的对象列表。在某些情况下,依赖会走得更远。

是否Lock()“知道”需要锁定的所有内容?

还显示了下面脚本的输出。脚本的目的主要是为了讨论 - 它不会失败,但我不相信它会锁定它需要的一切。

start:   [array([0, 1]), array([0, 1, 2]), array([0, 1, 2, 3])]
append an object
done!
finish:  [array([505, 605]), array([10, 11, 12]), array([10, 11, 12, 13]), array([5])]


import time
from threading import Thread, Lock
import numpy as np

class Bucket(object):
    def __init__(self, objects):
        self.objects = objects

class Object(object):
    def __init__(self, array):
        self.array = array

class A(Thread):
    def __init__(self, bucket):
        Thread.__init__(self)
        self.bucket      = bucket
    def run(self):
        nloop            = 0
        locker           = Lock()
        n = 0
        while n < 10:
            with locker:  
                objects = self.bucket.objects[:]  # makes a local copy of list each time
            for i, obj in enumerate(objects):
                with locker:
                    obj.array += 1
                time.sleep(0.2)
            n += 1
            print 'n: ', n
        print "done!"
        return

objects = []
for i in range(3):
    ob = Object(np.arange(i+2))
    objects.append(ob)
bucket = Bucket(objects)

locker           = Lock()

a = A(bucket)
print [o.array for o in bucket.objects]

a.start()

time.sleep(3)

with locker:
    bucket.objects.append(Object(np.arange(1)))  # abuse the bucket!
    print 'append an object'
time.sleep(5)

print [o.array for o in bucket.objects]
Run Code Online (Sandbox Code Playgroud)

Roc*_* Li 6

不知道您正在尝试做的任何事情。它只是一把锁,它不在乎你把它放在哪里。

例如,您可以声明:

lock = threading.Lock()
Run Code Online (Sandbox Code Playgroud)

进而:

with lock:
    # Do stuff.

# In another thread
with lock:
    # Do something else
Run Code Online (Sandbox Code Playgroud)

with lock除非当前块完成,否则所有其他块都无法执行,它与块中的内容无关。所以对于这个实例,假设第一个#Do stuff正在运行,当第二个线程命中时with lock: # Do something else,它不会运行,因为有相同的锁。self.lock如果您正在进行面向对象的编程,使用是一个好主意。


Jea*_*bre 5

你似乎误解了锁的工作原理。

锁不锁定任何对象,它只能锁定线程执行

尝试进入with locker:块的第一个线程成功。

如果另一个线程试图进入一个with locker:块(具有相同的locker对象),它会延迟到第一个线程退出该块,因此两个线程不能同时更改块内变量的值。

在这里,您的“共享资源”是您在块中更改的变量:如我所见,objectsobj.array. 您基本上是在保护它们免受并发访问(即 - 在没有初学者 GIL 的 Python 版本中)只是因为一次只有一个线程可以更改它们

旧人称之为临界区,一次只能执行 1 个线程。

请注意,locker对不同的资源使用相同的对象有点可疑。这有更多的机会死锁/比它需要的更慢。

(如果你嵌套 2 个with locker调用,你会遇到一个死锁——如果你想这样做,你需要一个 RLock)

就是这么简单。