对python实例类运用同步锁装饰器
多线程程序最令人头疼的便是各种锁,写起来麻烦也容易出错。 还好Python中有装饰器这种方便的神器存在,我们只需像单线程一样写程序 ,然后在外边包上同步锁装饰器就ok了。比如:
import threading def sync(lock): def syncWithLock(fn): def newFn(*args,**kwargs): lock.acquire() try: return fn(*args,**kwargs) finally: lock.release() newFn.func_name = fn.func_name newFn.__doc__ = fn.__doc__ return newFn return syncWithLock lock = threading.Lock() @sync(lock) def fn(): global x for i in range(10): x+=1 if __name__ == "__main__": x = 0 th = threading.Thread(target=fn) th2 = threading.Thread(target=fn) th3 = threading.Thread(target=fn) th.start() th2.start() th3.start() th.join() th2.join() th3.join() print x#30
如此,我们便可以派出多个线程来执行fn方法,而不用担心出现数据出错。然而有时候我们需要对实例方法加锁,一般来说该如何写呢?
class Test(object): def __init__(self): self.lock = threading.Lock() @sync(self.lock) def fn(self): pass
然而很遗憾,@sync(self.lock)里的self并无所指,而我们又无法得到实例对象本身的引用。很头疼,然而python的动态语言特性又使我们可以通过一些特别的方法来实现目的,目前我是这么做的:
class Test(object): def __init__(self): self.lock = threading.Lock() self.__decFns() def __decFns(self): @sync(self.lock) def __fn(): pass self.fn = __fn
我们编写了一个帮助函数__decFns,用来帮助我们间接实现对实例方法的加锁,在__decFns里我们就可以获取实例的引用self进行加锁,然后把相应的方法绑定到方法接口供外部使用。 虽然解决了问题,但是总觉的不太好看,读者若有更好思路欢迎讨论。