簡體   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