Python 如何销毁由threading.lock()创建的锁对象?

Python 如何销毁由threading.lock()创建的锁对象?,python,multithreading,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

如何销毁由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']中的lock对象?

我将把这部分移到前面,因为它可能是最重要的部分

您是否有一些有意义的理由重新检入由
dct['a']
引用的锁对象?如果你没有,那么。。。然后,首先不要将其存储在dict中,或者当您知道不再关心它时,只需手动
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']
再次强调一下,仅仅因为你从这个字典中删除了它,就意味着你删除了对这个对象的特定引用。只有当所有线程退出时,才会没有现存的引用,从而允许gc实际销毁对象

继续深入讨论如果需要在主线程中继续“签入”这个锁对象,应该怎么做


如何销毁dict['b']中的锁对象

不要这样做,至少不要手动操作——让python的gc为您这样做。你需要更高一级的工作——管理你的推荐信

如果要保留
Lock
对象的集合,请将其设置为
weakref
s的集合。Python的垃圾收集器通过执行引用计数来工作,并且通过只存储weakrefs,您不会阻止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
一旦任何线程不再(强烈地)引用
锁,它就会被垃圾收集(立即,在cpython中,可能稍后在其他python实现中)。一些注意事项:

  • 不要给dict命名
    dict
    。屏蔽内置的
  • 从技术上讲,我在上面的代码中有一个轻微的竞争条件——我依赖于第一个线程保持足够长的活动时间,以便第二个线程启动。显然,对于一个巨大的
    sleep(5)
    ,这不是问题,但是对于寿命极短的线程,可能需要一个更复杂的引用管理策略
  • 虽然主线程底部的
    While dct['a']():
    块似乎类似于
    join()
    调用,但实际上并不依赖于GC行为来管理程序控制。人们可以搞乱
    gc
    ,甚至可以在使用非refcounting的gc策略的python上运行代码
  • 请注意,即使weakref引用的锁被GC’d,您的dict中仍然有一个
    weakref
    对象。即使过时的对象只指向
    None
    ,如果您的程序特别长,您仍然需要定期检查并清除它们

你说的“销毁”是什么意思?你说的“销毁锁”是什么意思?可以使用Lock类的release()方法释放Lock对象。我试图删除Lock对象以避免内存泄漏。这可能吗?Python会自动处理这些事情。如果我的代码是一个守护进程,我不知道Python如何“自动处理这些事情”。是的,我确实需要与一组线程共享一个锁,比如dct['a']。和ct['b']与另一组线程。使用weakref,并在dct变得毫无意义时不断清洁dct。遵循此处建议的使用weakref的类似方法。但是获取以下错误:AttributeError:“非类型”对象没有属性“释放”(第一次)AttributeError:“非类型”对象没有属性“获取”(之后)