我是python的新手,目前正在尝试学习线程。我厌倦了使用锁来使我的资源线程安全,因为它们本身并不绑定到资源,所以每次我的代码与资源交互时,我一定会忘记获取和/或释放它们。相反,我希望能够“包装”(或装饰?)一个对象,这样它的所有方法和属性getter/setter都是原子的。如下所示:
state = atomicObject(dict())
# the following is atomic/thread-safe
state["some key"] = "some value"
这个是可能的吗?如果是这样,实现它的“最佳实践”方式是什么?
编辑:上述问题的一个很好的答案可以在How to make built-in containers (sets, dicts, lists) thread safe?中找到。然而,正如abarnert和jsbueno所展示的那样,我提出的解决方案(自动化锁)通常不是一个好主意,因为确定原子操作的适当粒度需要一些智能,并且很可能很难(或不可能)正确地实现自动化。
问题仍然存在,锁没有以任何方式绑定到它们应该保护的资源,所以我的新问题是:什么是将锁与对象关联的好方法?
建议的解决方案#2:我想可能有一种方法可以将锁绑定到对象,这样在没有首先获取锁的情况下尝试访问该对象会抛出错误,但我可以看到这是如何变得棘手的。
编辑:以下代码与问题不太相关。我发布它是为了证明我曾试图自己解决这个问题,但在发布这个问题之前迷失了方向。
根据记录,我编写了以下代码,但它不起作用:
import threading
import types
import inspect
class atomicObject(object):
def __init__(self, obj):
self.lock = threading.RLock()
self.obj = obj
# keep track of function handles for lambda functions that will be created
self.funcs = []
# loop through all the attributes of the passed in object
# and create wrapped versions of each attribute
for name in dir(self.obj):
value = getattr(self.obj, name)
if inspect.ismethod(value):
# this is where things get really ugly as i try to work around the
# limitations of lambda functions and use eval()... I'm not proud of this code
eval("self.funcs.append(lambda self, *args, **kwargs: self.obj." + name + "(*args, **kwargs))")
fidx = str(len(self.funcs) - 1)
eval("self." + name + " = types.MethodType(lambda self, *args, **kwargs: self.atomize(" + fidx + ", *args, **kwargs), self)")
def atomize(self, fidx, *args, **kwargs):
with self.lock:
return self.functions[fidx](*args, **kwargs)
我可以创建一个atomicObject(dict()),但是当我尝试向对象添加值时,我得到错误消息:"atomicObject不支持项分配“。
https://stackoverflow.com/questions/15960881
复制相似问题