user3761555
user3761555

Reputation: 1275

python: With GIL, is it still possible to have deadlocks with threading? (Not multi-processing)

python: With GIL, is it still possible to have deadlocks with threading? (Not multi-processing)

Below code will produce deadlock situation (Updated per Amadan, added sleep):

import threading
import time

# Two resources
resource1 = threading.Lock()
resource2 = threading.Lock()

def function1():
    with resource1:
        print("Thread 1 acquired resource 1")
        time.sleep(3)
        with resource2:
            print("Thread 1 acquired resource 2")
            time.sleep(3)

def function2():
    with resource2:
        print("Thread 2 acquired resource 2")
        time.sleep(3)
        with resource1:
            print("Thread 2 acquired resource 1")
            time.sleep(3)

# Create two threads
thread1 = threading.Thread(target=function1)
thread2 = threading.Thread(target=function2)

# Start the threads
thread1.start()
thread2.start()

# Wait for both threads to finish
thread1.join()
thread2.join()

print("Both threads finished execution")

But conceptually, even with GIL, the two threads can still trying to acquire a lock/resource that's already been acquired by the other thread.

Upvotes: 0

Views: 205

Answers (1)

Amadan
Amadan

Reputation: 198456

Your code can deadlock (it did for me on at least one run), but it depends on the one thread executing with resource between the time the other thread's two with resource statements.

GIL cannot prevent this deadlock. All it does is says Python can't execute more than one thread's Python code at a time. However, if thread1 executes with resource1 completely, thread2 executes with resource2 completely, before the second set of with resource is executed, it is a deadlock, GIL or no GIL.

If this specific timing does not happen, your code will not deadlock. For example, if thread1 manages to get through both of its with resource statements without the control being passed to thread2, you're safe. Obviously, if the code has any chance of deadlock, it is bad code, but it is not that easy to notice it since it is so dependent on timing, and so, chance.

To make the deadlock a certainty, try to put time.sleep(1) between the two with resource statements in each function. It doesn't change the logic in any way, but it will make sure that the first set of with resource statements is executed before the second set, triggering the deadlock situation.

Upvotes: 2

Related Questions