我有如下代码:
class SomeSharedData(object):
def __init__(self):
self._lock = RLock()
self._errors = 0
@property
def errors(self):
with self._lock:
return self._errors
@errors.setter
def errors(self, value):
with self._lock:
self._errors = value
除非有更多属性,如errors
。我的目标是易于使用,而不是效率,因此过度锁定是可以的。在
有没有更简洁的方法来定义这些属性?
到目前为止,我想到的最好的方法是:
^{pr2}$想法?更好的方法?
原始代码和新方法都会在data.errors += 1
之类的语句上遇到可能的竞争条件,但我很少需要执行这些操作,因此我在需要的地方添加了解决方法。在
谢谢你!在
您可能需要仔细考虑线程安全到底意味着什么。请考虑是否改为编写以下代码:
这段代码与您发布的代码一样是线程安全的。在Python中,将值赋给属性是线程安全的:该值总是被赋值的;它可能被另一个线程指定的另一个值覆盖,也可能不会被覆盖,但是您总是得到一个或另一个值,而不是两者的混合。同样地,访问该属性可以得到当前值。在
代码中断的地方是,正如您在原始版本或简化版本中所说的,例如:
^{pr2}$不是线程安全的,但这是使代码安全的关键,这些是您需要注意的事情,而不是简单的get/set。在
回答评论中的问题:
Python中的简单赋值只是重新绑定一个名称(而不是复制),并且保证是原子的;可以得到一个值或另一个值。但是,对属性(或下标变量)的赋值可以像在上面的属性中那样被重写。在这种情况下,属性赋值可能会中断。所以答案是属性赋值通常是安全的,但是如果属性赋值被属性或者setattr或者类似的东西覆盖了,那么就不安全了。在
另外,如果要替换的旧值是一个带有析构函数的Python类,或者包含一个具有析构函数的Python类,则析构函数代码可以在赋值过程中运行。Python仍然会确保它自己的数据结构不会被破坏(所以您永远不会得到segfault),但它不会为您自己的数据结构做同样的事情。最明显的解决方法是永远不要在任何类上定义del。在
相关问题 更多 >
编程相关推荐