我有这个实现:
def mlock(f):
'''Method lock. Uses a class lock to execute the method'''
def wrapper(self, *args, **kwargs):
with self._lock:
res = f(self, *args, **kwargs)
return res
return wrapper
class Lockable(object):
def __init__(self):
self._lock = threading.RLock()
我在几个地方使用,例如:
class Fifo(Lockable):
'''Implementation of a Fifo. It will grow until the given maxsize; then it will drop the head to add new elements'''
def __init__(self, maxsize, name='FIFO', data=None, inserted=0, dropped=0):
self.maxsize = maxsize
self.name = name
self.inserted = inserted
self.dropped = dropped
self._fifo = []
self._cnt = None
Lockable.__init__(self)
if data:
for d in data:
self.put(d)
@mlock
def __len__(self):
length = len(self._fifo)
return length
...
应用程序非常复杂,但效果很好。为了确保,我一直在对正在运行的服务进行压力测试,我发现它有时(很少)在mlock
中出现死锁。我假设另一个线程持有锁而不释放它。我该怎么调试呢?请注意:
我想知道:
我还有哪些选项可以进一步调试?
我一直在检查是否有任何方法可以知道什么线程持有RLock
,但似乎没有API。
答案 0 :(得分:1)
我认为这不是一个简单的解决方案,但可以通过一些工作完成。
就个人而言,我发现以下内容很有用(尽管在C ++中)。
首先创建一个使用曲目线程的Lockable
基础'与它的互动。 Lockable
对象将使用一个额外的(非递归)锁来保护字典映射线程ID与它的交互:
此外,Lockable
对象将具有低优先级线程,很少唤醒(每隔几分钟一次),并查看是否有死锁指示(由事件表示近似)线程长时间持有锁,而至少有一个其他线程等待它。)
因此,线程的条目应包括:
问题是这可能会改变线程的相对时间,这可能会导致程序进入与通常不同的执行路径。
在这里,你需要发挥创意。您可能还需要在这些(可能还有其他)操作中引发(随机)时间流逝。