How to thread lock 2 simple threads in Python

Question:

I am trying to demonstrate thread locking using a simple example, but unable to get it to work. My code uses locks and releases on two threads that simply print out a message. I have tried multiple variations, including removing the time.sleep() and passing the lock to the threads as an argument, but I’m obviously missing something fundamental about how locks work.

import threading
import time

thread_lock = threading.Lock()

ctr = 0

def thread_1():
    while True:
        global ctr
        thread_lock.acquire()
        ctr += 1
        print(ctr, 'thread_1 has added 1 to ctr')
        time.sleep(1)
        thread_lock.release()

def thread_2():
    while True:
        global ctr
        thread_lock.acquire()
        ctr += 1
        print(ctr, 'thread_2 has added 1 to ctr')
        time.sleep(1)
        thread_lock.release()

t_1 = threading.Thread(target=thread_1)
t_2 = threading.Thread(target=thread_2)

t_1.start()
t_2.start()

# t_1.join()
# t_2.join()
Asked By: Ben

||

Answers:

The code below demonstrates how using two locks usually results in the two threads alternating:

import threading
import time

lock1 = threading.Lock()
lock2 = threading.Lock()

ctr = 0
run = True

def thread_1():
    global ctr
    print('thread_1')
    while run:
        lock1.acquire()
        time.sleep(0.001)
        lock2.acquire()
        ctr += 1
        print(ctr, 'thread_1 has added 1 to ctr')
        time.sleep(1)
        lock1.release()
        time.sleep(0.001)
        lock2.release()
        time.sleep(0.001)

def thread_2():
    global ctr
    print('thread_2')
    time.sleep(0.001)
    while run:
        lock1.acquire()
        time.sleep(0.001)
        lock2.acquire()
        ctr += 1
        print(ctr, 'thread_2 has added 1 to ctr')
        time.sleep(1)
        lock1.release()
        time.sleep(0.001)
        lock2.release()
        time.sleep(0.001)

t_1 = threading.Thread(target=thread_1)
t_2 = threading.Thread(target=thread_2)

t_1.start()
t_2.start()

while ctr < 5:
    time.sleep(0.1)
    
run = False
print('joining...')
t_1.join()
t_2.join()

Usual output:

thread_1
thread_2
1 thread_1 has added 1 to ctr
2 thread_2 has added 1 to ctr
3 thread_1 has added 1 to ctr
4 thread_2 has added 1 to ctr
5 thread_1 has added 1 to ctr
joining...
6 thread_2 has added 1 to ctr
Answered By: quamrana