Python3 : can I lock multiple locks simultaneously?

I have multiple locks that lock different parts of my API.

To lock any method I do something like this :

import threading

class DoSomething:
    def __init__():
        self.lock = threading.Lock()

    def run(self):
        with self.lock:
            # do stuff requiring lock here

And for most use cases this works just fine.

But, I am unsure if what I am doing when requiring multiple locks works or not :

import threading

class DoSomething:
    def __init__():
        self.lock_database = threading.Lock()
        self.lock_logger = threading.Lock()

    def run(self):
        with self.lock_database and self.lock_logger:
            # do stuff requiring lock here

As it is, the code runs just fine but I am unsure if it runs as I want it to.

My question is : are the locks being obtained simultaneously or is the first one acquired and only then the second is also acquired.

Is my previous code as follows ?

with self.lock1:
    with self.lock2:
        # do stuff here

As it is, the code currently works but, since the chances of my threads requiring the same lock simultaneously is extremely low to begin with, I may end up with a massive headache to debug later

I am asking the question as I am very uncertain on how to test my code to ensure that it is working as intended and am equally interested in having the answer and knowing how I can test it to ensure that it works ( and not end up with the end users testing it for me )

Upvotes: 6

Views: 3017

Answers (1)

Solomon Slow
Solomon Slow

Reputation: 27190

Yes, you can do that, but beware of deadlocks. A deadlock occurs when one thread is unable to make progress because it needs to acquire a lock that some other thread is holding, but the second thread is unable to make progress because it wants the lock that the first thread already is holding.

Your code example locks lock_database first, and lock_logger second. If you can guarantee that any thread that locks them both will always lock them in that same order, then you're safe. A deadlock can never happen that way. But if one thread locks lock_database before trying to lock lock_logger, and some other thread tries to grab them both in the opposite order, that's a deadlock waiting to happen.

Looks easy. And it is, except...

...In a more sophisticated program, where locks are attached to objects that are passed around to different functions, then it may not be so easy because one thread may call some foobar(a, b) function, while another thread calls the same foobar() on the same two objects, except the objects are switched.

Upvotes: 7

Related Questions