如何销毁threading.Lock()创建的锁对象?

时间:2014-09-06 12:29:03

标签: python multithreading

如何销毁threading.Lock()创建的锁对象?例如,

import time
from threading import Thread
import threading

dict = {}

dict['a']=threading.Lock()
dict['b']=threading.Lock()

def myfunc(group, i, lck):
    with lck:
        print "group %s sleeping 5 sec from thread %d" % (group, i)
        time.sleep(5)
        print "finished sleeping from thread %d" % i

for i in range(5):
    t = Thread(target=myfunc, args=('a', i, dict['a']))
    t.start()

for i in range(5):
    t = Thread(target=myfunc, args=('b', i, dict['b']))
    t.start()

如何在dict ['b']中销毁锁定对象?

1 个答案:

答案 0 :(得分:1)

我会把这部分放在前面,因为它可能是最重要的。

您是否有一些有意义的理由要重新检入dct['a']引用的锁定对象?如果你不这样做,那么......或者首先将它存储在一个字典中,或者当你知道你不再关心它时只需手动del dct['a']。这样做只是将引用删除到你的dict持有的锁,而不是对象本身。

for i in range(5):
    t = Thread(target=myfunc, args=('a', i, dct['a']))
    t.start()

# some more operations that use dct['a'] would probably happen here,
# else why did we put it there in the first place...
del dct['a']

再次强调它,仅仅因为你del它只是意味着你删除了对该对象的特定引用。只有当你的所有线程退出时,才会有现存的引用,允许gc实际销毁该对象。

如果您需要在主线程中对此锁定对象进行“检入”,请进行更深入的讨论。


  

如何在dict ['b']中销毁锁定对象?

不要,至少不要手动 - 让python的gc为你做这件事。您需要提高一级 - 管理您的参考

如果要保留Lock个对象的集合,请将其设为weakref的集合。 Python的垃圾收集器通过引用计数来工作,并且只存储weakref,你不会阻止gc做它的事情。例如:

import time
from threading import Thread
import threading
import weakref

dct = {}

def myfunc(group, i, lck):
    if callable(lck):
        #lck is a weakref, get the actual lock from it
        lck = lck()
    with lck:
        print "group %s sleeping 5 sec from thread %d" % (group, i)
        time.sleep(5)
        print "finished sleeping from thread %d" % i

for i in range(5):
    lock = dct.get('a', threading.Lock())
    t = Thread(target=myfunc, args=('a', i, lock))
    if 'a' not in dct:
        dct['a'] = weakref.ref(lock)
    t.start()

while dct['a']():
    print 'lock still alive'
    time.sleep(3)

print 'lock is dead, jim'

输出:

ben@nixbox:~$ python threadtest.py 
group a sleeping 5 sec from thread 0
lock still alive
lock still alive
finished sleeping from thread 0
group a sleeping 5 sec from thread 1
lock still alive
...
lock still alive
finished sleeping from thread 4
lock is dead, jim

一旦任何线程不再(强烈)引用Lock,它就会被垃圾收集(立即,在cpython中,可能在其他python实现中稍后)。一些说明:

  • 不要将dicts命名为dict。掩盖内置的。
  • 我在上面的代码中技术上有轻微的竞争条件 - 我依赖第一个线程保持活动足够长的时间来启动第二个线程。显然有一个巨大的sleep(5),这是一个非问题,但对于极短期的线程可能需要更复杂的参考管理策略。
  • 虽然主线程底部的while dct['a']():块看起来类似于join()调用,但实际上不依赖于GC行为来管理程序控制。人们可以搞砸gc,甚至可以在使用除引用计数之外的gc策略的python上运行你的代码。
  • 请注意,即使在weakref引用的锁定得到GC后,您仍然有一个weakref对象位于您的词典中。即使陈旧的只是指向None,如果您的程序特别长寿,您仍然需要定期检查并清理它们。