繁体   English   中英

asyncio 尝试获取锁而不等待它

[英]asyncio try to acquire a lock without waiting on it

我正在将一些线程代码转换为 asyncio。

在线程代码中,我调用 threading.RLock.acquire(blocking = False, timeout = 0)

似乎没有办法在不等待的情况下尝试获取 asyncio.Lock。 有没有办法做到这一点,如果是这样,我错过了什么?

如果有帮助,这是我的助手 function:

@contextlib.contextmanager
def try_acquire_lock ( lock: gevent.lock.RLock ) -> Iterator[bool]:
    try:
        locked: bool = lock.acquire ( blocking = False, timeout = 0 )
        yield locked
    finally:
        if locked:
            lock.release()

这是我如何使用它的示例:

    def generate( self, cti: Freeswitch_acd_api ) -> bool:
        log = logger.getChild( 'Cached_data._generate' )
        if self.data_expiration and tz.utcnow() < self.data_expiration:
            log.debug( f'{type(self).__name__} data not expired yet' )
        else:
            with try_acquire_lock( self.lock ) as locked:
                if locked:
                    log.debug( f'{type(self).__name__} regenerating' )
                    try:
                        new_data = self._generate( cti )
                    except Freeswitch_error as e:
                        log.exception( 'FS error trying to generate data: %r', e )
                        return False
                    else:
                        self.data = new_data
                        self.data_expiration = tz.utcnow() + tz.timedelta( seconds=self.max_cache_seconds )
        return True

因为肯定有人会问“你为什么要这样做”,这是因为在某些情况下我有 3 个不同的线程(现在是任务),每个线程都连接到不同的服务器。 这些任务负责使用来自每个服务器的信息更新 state。 我可以从任何一台服务器获得一些“全局”信息。 如果一个任务已经在更新该全局信息,我不希望另一个任务重复该工作,所以我使用锁来控制当前谁在执行该过程。 我需要能够从所有服务器获取信息的原因是因为有时会关闭一个服务器进行维护,这是我能想到的最简单最简单的方法来实现它而无需创建与服务器的额外连接。

可以尝试使用 Lock.locked() 方法,返回一个 boolean 值表示当前是否持有锁。 您可以使用此方法检查锁当前是否被另一个任务持有,如果是,您可以选择跳过需要锁的代码或采取一些其他操作。

如何使用 Lock.locked() 尝试在不等待的情况下获取锁的示例:

import asyncio


async def main():
    lock = asyncio.Lock()

    if not lock.locked():
        # Lock is not held by another task, so we can acquire it
        async with lock:
            print("Acquired lock")
            # Do some work that requires the lock here
    else:
        # Lock is already held by another task, so we cannot acquire it
        print("Lock is held by another task, skipping code that requires the lock")

asyncio.run(main())

或者,您可以使用 Lock.acquire() 方法并将 blocking=False 参数传递给它,以尝试在不等待的情况下获取锁。 如果成功获取锁,则返回 True,否则返回 False。

    import asyncio
    
    async def main():
    lock = asyncio.Lock()
    
    if await lock.acquire(blocking=False):
        # Lock was acquired successfully
        print("Acquired lock")
        # Do some work that requires the lock here
        lock.release()
    else:
        # Lock is already held by another task, so we cannot acquire it
        print("Lock is held by another task, skipping code that requires the lock")

asyncio.run(main())

告诉我它是否有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM