python 中的头部安全对象和字典类型
我有两个关于在 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}
I have two questions about creating thread safe types in python, and one related question about multiple inheritance.
1) Are there any problematic implications with using the following subclasses in my threaded application as a sort of "lazy" thread-safe type? I realize that whomever sets values which may be altered by other threads bears the responsibility to ensure those values are thread safe as well.
2) Another question I have is if there exists more prudent alternatives to these types within python in a typical installation.
Example:
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) If both of the types defined above could be considered reasonably safe, what negative implications would be faced by using multiple inheritance to create a type that supported a mixture of both of these modifications, and does my example inherit those classes in the optimal order?
Example:
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)
Edit:
Just another example of another type inheriting both of the former types, and testing using 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}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
至于你的第一个问题和第二个问题,
dict
、list
等类型已经是线程安全的。您不必为它们添加线程安全性。不过您可能会发现这很有用。它是一个装饰器,基本上实现了 Java 中的synchronized
关键字,使用函数作用域来定义关键部分。使用类似的方法也可以创建一个面向threading.Condition的装饰器。像这样使用它(如果过度使用它,请注意死锁):
在第三个问题上, Python教程指出继承属性的搜索顺序是深度优先、左优先。因此,如果您继承
(myclass, dict)
,则应使用myclass
中的__setitem__
方法。 (在旧版本的 Python 中,教程中的同一部分暗示这种选择是任意的,但现在它似乎是经过深思熟虑的。)我从发布的源代码中弗洛伊德式的分号错误中猜测您是新手Python,但在 Java 或 C# 方面经验丰富。如果是这样,您需要记住,属性(方法)解析发生在 Python 的运行时,并且类以及实例都是可以在以下位置检查/探索的一流对象:运行时间。
首先搜索实例属性字典,然后搜索类属性,然后启动父类搜索算法。这是通过(概念上)相当于重复的
hasattr(class_or_instance, attribute)
调用来完成的。下面确认了对于“新式”类(从
object
继承的类,在 2.x 语言规范中是可选的),每次查找属性时都会发生此解析。当创建类(或子类)或创建实例时,不会完成此操作。 (这是在版本 2.7.2 中完成的。)替换类
Foo
的方法会更改已定义的子类和已创建的实例的行为。As to your first and second questions, the
dict
,list
, etc. types are already thread-safe. You do not have to add thread safety to them. However you may find this useful. It's a decorator that basically implements thesynchronized
keyword from Java, using function scope to define a critical section. Using a similar approach it is possible to author athreading.Condition
oriented decorator also.Use it like this (and beware deadlocks if you overuse it):
On the third question, the Python tutorial states that the search order for inherited attributes is depth-first, left-first. So if you inherit
(myclass, dict)
then the__setitem__
method frommyclass
should be used. (In older versions of Python, this same section in the tutorial implied that this choice was arbitrary, but nowadays it appears to be quite deliberate.)I'm guessing from the Freudian slip of a semicolon in the posted source that you are new to Python but experienced in either Java or C#. If so you will need to keep in mind that attribute (method) resolution occurs at run time in Python, and that the classes as well as the instance are first-class objects that can be inspected/explored at run time.
First the instance attribute dictionary is searched, then the class attributes, and then the parent class search algorithm starts. This is done with (conceptually) the equivalent of repeated
hasattr(class_or_instance, attribute)
calls.The below confirms that for "new-style" classes (classes that inherit from
object
, which in the 2.x language specification is optional), this resolution occurs each time the attribute is looked up. It is not done when the class (or subclass) is created, or when instances are created. (This was done in release 2.7.2.)Replacing the method of class
Foo
changes the behavior of subclasses already defined and of instances already created.