2011-07-21 60 views
6

所以,我有一個多線程的Python程序,目前正在遭受死鎖。我正想通過子類對象threading.Lock登錄鎖定取得:是否可以在Python中繼承Lock()對象?如果沒有,調試死鎖的其他方法?

import traceback 
class DebugLock(threading.Lock): 
    def acquire(self): 
     print >>sys.stderr, "acquired", self 
     #traceback.print_tb 
     threading.Lock.acquire(self) 
    def release(self): 
     print >>sys.stderr, "released", self 
     #traceback.print_tb 
     threading.Lock.release(self) 

當我嘗試運行該程序,我得到以下錯誤:

class DebugLock(threading.Lock): 
TypeError: Error when calling the metaclass bases 
    cannot create 'builtin_function_or_method' instances 

所以,我的問題是雙重的:

  1. 是否有可能繼承Lock對象來做我正在做的事情?

  2. 如果沒有,在python中調試死鎖的最佳方法是什麼?

注意:我沒有編寫任何Python擴展。還有一個類似的問題:How to debug deadlock with python? 但是,它涉及編譯C++代碼和使用GDB,由於我的代碼是純Python,所以我不能這樣做。

回答

13

你可以只使用「有鎖」與「是鎖」的辦法,就像這樣:

import threading, traceback, sys 
class DebugLock(object): 
    def __init__(self): 
     self._lock = threading.Lock() 
    def acquire(self): 
     print >>sys.stderr, "acquired", self 
     #traceback.print_tb 
     self._lock.acquire() 
    def release(self): 
     print >>sys.stderr, "released", self 
     #traceback.print_tb 
     self._lock.release() 
    def __enter__(self): 
     self.acquire() 
    def __exit__(self, type, value, traceback): 
     self.release() 

在那裏我已經在適當的範圍內侍衛,因爲你可能會拋出要使用的with你的鎖的語法(誰不會?)。如下圖所示

用法:

 
    >>> lock = DebugLock() 
    >>> with lock: 
    ...  print "I'm atomic!" 
    ... 
    acquired <__main__.DebugLock object at 0x7f8590e50190> 
    I'm atomic! 
    released <__main__.DebugLock object at 0x7f8590e50190> 
    >>> 
+0

謝謝,即使這樣! – jmite

4

拉斯回答的重要問題(#2),我會回答問題#1。

看起來不可能。 threading.Lock()是一個工廠函數(documentation)。它調用thread.allocate_lock() - 無法控制Lock對象的創建。你也不能monkeypatch thread.LockType類定義(在thread.pi中公開的類骨架)。

>>> thread.LockType.foo = "blah" 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: can't set attributes of built-in/extension type 'thread.lock' 
2

如果你想要做的事如繼承,而不會在這個錯誤,我建議你試試

import traceback 
from threading import Lock 
class DebugLock(): 
    def __init__(self,lock = None): 
     self.lock = lock or Lock() 

     # normally done with __dict__ 
     for command in dir(self.lock): 
      self.__dict__[command] = getattr(self.lock,command) 

我使用self.__dict__.update(lock.__dict__)似乎並不奏效的常規方法。我與鎖定代碼

X = DebugLock() 
y = X.lock 
Y = DebugLock(y) 
X.acquire() 
Y.acquire() 
X.release() 
Y.release() 

和掛測試了這一點,所以我覺得這是工作。

相關問題