Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

non-blocking lock with 'with' statement

As far as I know, the following code will be blocked if lock is already acquired by another thread.

It seems that non-blocking can be implemented by lock.acquire(0), but instead I have to use try-finally block instead with block.

lock = threading.Lock()

def func():
 with lock:
  # do something...

Is there any method to implement non-blocking lock acquisition?

like image 739
JaeJun LEE Avatar asked Jul 19 '15 12:07

JaeJun LEE


People also ask

Is lock acquire blocking?

acquire allows a thread to take ownership of a lock. If a thread tries to acquire a lock currently owned by another thread, it blocks until the other thread releases the lock. At that point, it will contend with any other threads that are trying to acquire the lock.

What is non-blocking task?

In computer science, an algorithm is called non-blocking if failure or suspension of any thread cannot cause failure or suspension of another thread; for some operations, these algorithms provide a useful alternative to traditional blocking implementations.

What is non-blocking thread?

A task (thread) is non-blocking when it doesn't cause other tasks (threads) to wait until the task is finished.

What is the difference between threading lock and threading RLock?

Lock can only be acquired once, and once acquired it cannot be acquired again by the same thread or any other thread until it has been released. A threading. RLock can be acquired more than once by the same thread, although once acquired by a thread it cannot be acquired by a different thread until it is been released.


2 Answers

@contextmanager
def nonblocking(lock):
    locked = lock.acquire(False)
    try:
        yield locked
    finally:
        if locked:
            lock.release()

lock = threading.Lock()
with nonblocking(lock) as locked:
    if locked:
        do_stuff()
like image 116
Николай Коновалов Avatar answered Sep 18 '22 16:09

Николай Коновалов


Is there any method to implement non-blocking lock acquisition?

Yes. Just raise an exception if the lock can't be acquired immediately. Something like:

@contextlib.contextmanager
def non_blocking_lock(lock=threading.Lock()):
    if not lock.acquire(blocking=False):
        raise WouldBlockError
    try:
        yield lock
    finally:
        lock.release()

Usage:

with non_blocking_lock():
    # run with the lock acquired
like image 42
jfs Avatar answered Sep 18 '22 16:09

jfs