我有两个关于在python中创建线程安全类型的问题,以及一个关于多重继承的相关问题。
1)在我的线程应用程序中使用以下子类作为一种“懒惰”线程安全类型是否有任何问题?我意识到,任何设置可能被其他线程更改的值的人都有责任确保这些值也是线程安全的。
2)我遇到的另一个问题是,如果在典型安装中python中存在这些类型的更谨慎的替代方案。
示例:
from threading import Lock
from __future__ import with_statement
class safedict(dict):
def __init__(self,*args,**kwargs):
self.mylock=Lock();
super(safedict, self).__init__(*args, **kwargs)
def __setitem__(self,*args,**kwargs):
with self.mylock:
print " DEBUG: Overloaded __setitem__ has the lock now."
super(safedict,self).__setitem__(*args,**kwargs)
class safeobject(object):
mylock = Lock(); # a temporary useless lock, until we have a proper instance.
def __init__(self,*args,**kwargs):
self.mylock=Lock();
super(safeobject, self).__init__(*args, **kwargs)
def __setattr__(self,*args,**kwargs):
with self.mylock:
print " DEBUG: Overloaded __setattr__ has the lock now."
super(safeobject,self).__setattr__(*args,**kwargs)
3)如果上面定义的两种类型都被认为是相当安全的,那么使用多重继承创建支持这两种修改混合的类型将会面临什么负面影响,我的示例是否继承了这些类最佳顺序?
示例:
class safedict2(safeobject,dict):
def __setitem__(self,*args,**kwargs):
with self.mylock:
print " DEBUG: Overloaded __setitem__ has the lock now."
super(safedict2,self).__setitem__(*args,**kwargs)
编辑: 只是继承两种前一种类型的另一种类型的另一个例子,并使用ipython进行测试。
In [304]: class safedict3(safeobject,safedict):
.....: pass
.....:
In [305]: d3 = safedict3()
DEBUG: Overloaded __setattr__ has the lock now.
DEBUG: Overloaded __setattr__ has the lock now.
In [306]: d3.a=1
DEBUG: Overloaded __setattr__ has the lock now.
In [307]: d3['b']=2
DEBUG: Overloaded __setitem__ has the lock now.
In [308]: d3
Out[308]: {'b': 2}
答案 0 :(得分:1)
关于您的第一个和第二个问题,dict
,list
等类型已经是线程安全的。您不必为它们添加线程安全性。但是你可能会觉得这很有用。它是一个装饰器,基本上从Java实现synchronized
关键字,使用函数范围来定义关键部分。使用类似的方法,也可以创建一个threading.Condition
面向装饰器。
import threading
def tryfinally(finallyf):
u"returns a decorator that adds try/finally behavior with given no-argument call in the finally"
def decorator(callable):
def execute(*args, **kwargs):
try: result = callable(*args, **kwargs)
finally: finallyf()
return result
return execute
return decorator
def usinglock(lock):
u"returns a decorator whose argument will acquire the given lock while executing"
def decorator(function):
body = tryfinally(lock.release)(function)
def execute(*args, **kwargs):
lock.acquire()
return body(*args, **kwargs)
return execute
return decorator
def synchronized(function):
u"decorator; only one thread can enter the decorated function at a time; recursion is OK"
return usinglock(threading.RLock())(function)
像这样使用它(如果你过度使用它,请注意死锁):
@synchronized
def foo(*args):
print 'Only one thread can enter this function at a time'
关于第三个问题,Python tutorial表明继承属性的搜索顺序是深度优先,左先优先。因此,如果您继承(myclass, dict)
,则应使用__setitem__
中的myclass
方法。 (在旧版本的Python中,本教程中的相同部分暗示这种选择是任意的,但现在看起来是非常慎重的。)
我猜测来自发布源代码中的分号的Freudian单词,你是Python的新手,但在Java或C#中都有经验。如果是这样,您需要记住,在Python中运行时发生属性(方法)解析,并且类以及实例是可以在以下位置检查/探索的第一类对象运行时间。
首先搜索实例属性字典,然后搜索类属性,然后启动父类搜索算法。这是通过(概念上)相当于重复的hasattr(class_or_instance, attribute)
调用完成的。
下面确认对于“新式”类(继承自object
的类,在2.x语言规范中是可选的),每次查找属性时都会出现此解析。创建类(或子类)或创建实例时,不会执行此操作。 (这是在2.7.2版本中完成的。)
>>> class Foo(object):
... def baz(self):
... print 'Original Foo.baz'
...
>>> class Bar(Foo): pass
...
>>> def newprint(self):
... print 'New Foo.baz'
...
>>> x = Foo()
>>> y = Bar()
>>> Foo.baz = newprint
>>> a = Foo()
>>> b = Bar()
>>> map(lambda k: k.baz(), (x, y, a, b))
New Foo.baz
New Foo.baz
New Foo.baz
New Foo.baz
[None, None, None, None]
替换类Foo
的方法会更改已定义的子类和已创建的实例的行为。