python中构造函数/析构函数中的线程锁定/解锁

2024-05-16 14:18:07 发布

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

我有一个只能通过静态方法从外部访问的类。这些静态方法然后创建一个类的对象在方法中使用,然后它们返回并且对象可能被销毁。现在需要一对getter锁来访问config/setter类的文件。在

由于我有几个不同的静态方法,它们都需要对配置文件的读/写访问权限,这些文件都是在方法范围内创建对象的,所以我考虑在对象构造函数内部完成锁获取,然后在析构函数中释放。在

我的同事表示担心,如果发生什么事情,可能会导致类永远锁定。他还提到了关于垃圾收集器如何调用python中的析构函数的一些事情,但是我们对python都比较陌生,所以这是一个未知的问题。在

这是一个合理的解决方案还是应该在每个方法本身中锁定/解锁?在


Class A():
    rateLock = threading.RLock()
    chargeLock = threading.RLock()

    @staticmethod
    def doZStuff():
        a = A()
        a.doStuff('Z')

    @staticmethod
    def doYStuff():
        a = A()
        a.doStuff('Y')

    @synchronized(lock)
    def doStuff(self, type):
        if type == 'Z':
            otherstuff()
        elif type == 'B':
            evenmorestuff()

甚至可以让它在doStuff()上而不是{}上以这种方式工作吗

更新

谢谢大家的回答。我所面临的问题主要是因为异步访问我的模块没有实际意义,但这只是API的一部分。通过API访问我们的东西的团队抱怨并发性问题。所以我不需要完美的解决方案,我只是想让他们不会让我们这边崩溃,也不会拿回垃圾数据


Tags: 文件对象方法函数apideftype解决方案
3条回答

但是,如果你必须在构造函数和析构函数中获取和释放锁,那么你真的,真的,真的应该给你的设计另一个机会。你应该改变你的基本假设。在

在任何应用中:“锁”应该总是保持很短的时间-尽可能短。这意味着-在所有情况下,您将以释放锁的相同方法获取锁。在

几乎不应该有任何理由以RAII方式锁定/解锁对象。这不是它的本意;)

我给你举个例子:你管理一些资源,这些资源可以一次从多个线程读取,但是只有一个线程可以写入它们。在

在一个“幼稚”的实现中,每个对象都有一个锁,每当有人想写它时,你就会锁定它。当你决定写多个线程时,我们会很好地把它写出来,,然后我们就要写多个线程了。在

但是请理解锁,互斥-所有这些原语的创建只是为了同步你的源代码的几行。因此,与使锁成为可写对象的一部分不同,您只有一个非常短的时间内真正需要它的锁。你必须在你的界面上投入更多的时间和思想。但是,锁/互斥锁的“保持”时间从来不会超过几微秒。在

你对垃圾收集是正确的,所以这不是一个好主意。 查看decorator,用于编写同步函数。在

示例:http://code.activestate.com/recipes/465057-basic-synchronization-decorator/

编辑 我还不能百分之百确定你的想法,所以我的建议可能是错误的:

class A():
    lockZ = threading.RLock()
    lockY = threading.RLock()

    @staticmethod
    @synchroized(lockZ)
    def doZStuff():
        a = A()
        a.doStuff('Z')

    @staticmethod
    @synchroized(lockY)
    def doYStuff():
        a = A()
        a.doStuff('Y')

    def doStuff(self, type):
        if type == 'Z':
            otherstuff()
        elif type == 'B':
            evenmorestuff()
Class A():
    rateLock = threading.RLock()
    chargeLock = threading.RLock()

    def doStuff(self,ratefile,chargefile):
        with A.rateLock:
            with open(ratefile) as f:
                # ...
        with A.chargeLock:
            with open(chargefile) as f:
                # ...

使用with statement将保证成对获取和释放(R)锁。即使with块中发生异常,也将调用发布。在

您可能还需要考虑将锁尽可能紧密地放在文件访问块with open(...) as ...周围,这样锁的保留时间不会超过需要的时间。在

最后,a=a()的创建和垃圾回收不会影响锁 如果(如上所述)锁是类属性(与实例属性相反)。类属性位于A.__dict__,而不是a.__dict__。因此,在A本身被垃圾回收之前,锁不会被垃圾回收。在

相关问题 更多 >