1

有没有办法在python类中使用像java方法同步这样的监控线程同步来确保线程安全并避免竞争条件?

我想要一个类似监视器的同步机制,它只允许在我的类或对象中调用一个方法

4

2 回答 2

6

您可能想看看python threading interface。对于简单的互斥功能,您可以使用Lock对象。with您可以使用以下语句轻松完成此操作:

...
lock = Lock()
...
with (lock):
  # This code will only be executed by one single thread at a time
  # the lock is released when the thread exits the 'with' block
  ...

有关python 中不同线程同步机制的概述,另请参见此处。

Java没有python语言结构synchronized(但我想它可以使用装饰器构建)

于 2012-07-04T19:38:53.247 回答
1

我为它构建了一个简单的原型,这里是 GitHub 存储库的链接,了解所有详细信息:https ://github.com/ma-rahal/monitor-sync-python

我使用继承而不是装饰器,但也许我稍后会包含该选项
这是“监视器”超类的样子:

import threading

class Monitor(object):
   def __init__(self, lock = threading.Lock()):
       ''' initializes the _lock, threading.Lock() is used by default '''
       self._lock = lock


   def Condition(self):
       ''' returns a condition bound to this monitor's lock'''
       return threading.Condition(self._lock)

   init_lock = __init__

现在,定义自己的监视器所需要做的就是从这个类继承:

class My_Monitor_Class(Monitor):
    def __init__(self):
        self.init_lock() # just don't forget this line, creates the monitor's _lock
        cond1 = self.Condition()
        cond2 = self.Condition()
        # you can see i defined some 'Condition' objects as well, very simple syntax
        # these conditions are bound to the lock of the monitor

你也可以通过你自己的锁代替

class My_Monitor_Class(Monitor):
    def __init__(self, lock):
        self.init_lock(lock)

查看threading.Condition()文档

您还需要使用监视器的锁来保护所有“公共”方法,如下所示:

class My_Monitor_Class(Monitor):
    def method(self):
        with self._lock:
            # your code here

如果您想使用“私有”方法(在监视器内部调用),您可以使用保护它们_lock(否则线程会卡住),或者使用RLock代替监视器

额外提示

有时监视器由“入口”和“出口”协议组成

monitor.enter_protocol()
<critical section>
monitor.exit_protocol()

在这种情况下,您可以利用 python 的酷with语句 :3
只需定义__enter____exit__方法,如下所示:

class monitor(Monitor):
    def __enter__(self):
        with self._lock:
            # enter_protocol code here
    
    def __exit__(self, type, value, traceback):
        with self._lock:
            # exit_protocol code here

现在您需要做的就是使用with 语句调用监视器:

with monitor: 
    <critical section>
于 2020-12-11T02:24:14.023 回答