线程安全的Python属性/属性?

2024-10-01 09:22:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我有如下代码:

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之类的语句上遇到可能的竞争条件,但我很少需要执行这些操作,因此我在需要的地方添加了解决方法。在

谢谢你!在


Tags: 方法代码selflock属性objectinitvalue
1条回答
网友
1楼 · 发布于 2024-10-01 09:22:30

您可能需要仔细考虑线程安全到底意味着什么。请考虑是否改为编写以下代码:

class SomeSharedData(object):
    def __init__(self):
        self.errors = 0

这段代码与您发布的代码一样是线程安全的。在Python中,将值赋给属性是线程安全的:该值总是被赋值的;它可能被另一个线程指定的另一个值覆盖,也可能不会被覆盖,但是您总是得到一个或另一个值,而不是两者的混合。同样地,访问该属性可以得到当前值。在

代码中断的地方是,正如您在原始版本或简化版本中所说的,例如:

^{pr2}$

不是线程安全的,但这是使代码安全的关键,这些是您需要注意的事情,而不是简单的get/set。在

回答评论中的问题:

Python中的简单赋值只是重新绑定一个名称(而不是复制),并且保证是原子的;可以得到一个值或另一个值。但是,对属性(或下标变量)的赋值可以像在上面的属性中那样被重写。在这种情况下,属性赋值可能会中断。所以答案是属性赋值通常是安全的,但是如果属性赋值被属性或者setattr或者类似的东西覆盖了,那么就不安全了。在

另外,如果要替换的旧值是一个带有析构函数的Python类,或者包含一个具有析构函数的Python类,则析构函数代码可以在赋值过程中运行。Python仍然会确保它自己的数据结构不会被破坏(所以您永远不会得到segfault),但它不会为您自己的数据结构做同样的事情。最明显的解决方法是永远不要在任何类上定义del。在

相关问题 更多 >