Thread and Mutex#
This page describes the usage of threads and mutex in python.
Mutex in Python can be imported and used with the following statement :
from threading import Lock
Thread in Python can be imported and used with the following statement :
from threading import Thread
Warning
Thread instances from threading are executed concurrently (only one CPU core is used for all threads). If you want to execute threads by multiple core, so in a parallelism way, you must use this import statement :
from multiprocessing import Process
However, this page focuses only on concurrent threads.
How to use Mutex#
from threading import Lock
# create the mutex
mutex = Lock()
# acquire the mutex before a critical section
mutex.acquire()
print("Hello World)
# release once the critical section is finished
mutex.release()
Warning
Pay attention to the deadlock situation :
How to use Thread#
Two possibilities :
Create a Thread object and set it a target function
from threading import Thread
# function that will be executed by the thread
def processData(data):
print('Processing data: {}'.format(data))
# creating a few threads
for i in range(0, 10):
t = Thread(target=processData, args=(i))
# way to launch the thread
t.start()
Implement a class that inherits from Thread and overwrite both __init__() and run() methods
from threading import Thread
# the class Handler inherits from Thread
class Handler(Thread):
def __init__(self, client, userdata, msg):
Thread.__init__(self)
# will be executed when method start() is called
def run(self):
print("Hello World)
# create and start thread
handler = Handler()
handler.start()
Using Mutex to prevent conflicting usage of resources by different Threads#
Using Mutex with one single thread does not make much sense usually. However, with several Threads working either concurrently or in parallel, it all makes sense.
The following code :
#!/usr/bin/env python
import threading
def processData(data):
thread_id = threading.get_ident()
print('\nProcessing data:', data, "ThreadId:", thread_id)
counter = 0
max_run = 10
while True:
some_data = counter
t = threading.Thread(target=processData, args=(some_data))
t.start()
counter = counter + 1
if counter >= max_run:
break
will produce this output :
Processing data: 0 ThreadId: 13592
Processing data: 1 ThreadId: 22840
Processing data:
Processing data: 3 ThreadId: 17724
Processing data:
Processing data:
Processing data: 2 ThreadId: 5228
5 ThreadId: 18468
Processing data:
Processing data: 4 ThreadId: 2008
8 ThreadId: 4240
7 ThreadId: 25236
Processing data: 6 ThreadId: 21216
9 ThreadId: 11256
This is because the instances of Thread are trying to use the print() function simultaneously.
With a Mutex used before accessing the print() function, which is a critical section in a multi-threaded program :
#!/usr/bin/env python
import threading
mutex = threading.Lock()
def processData(data, thread_safe):
if thread_safe:
mutex.acquire()
try:
thread_id = threading.get_ident()
print('\nProcessing data:', data, "ThreadId:", thread_id)
finally:
if thread_safe:
mutex.release()
counter = 0
max_run = 10
thread_safe = False
while True:
some_data = counter
t = threading.Thread(target=processData, args=(some_data, thread_safe))
t.start()
counter = counter + 1
if counter >= max_run:
break
the output now looks much better :
Processing data: 0 ThreadId: 24996
Processing data: 1 ThreadId: 2008
Processing data: 2 ThreadId: 2076
Processing data: 3 ThreadId: 22288
Processing data: 4 ThreadId: 18396
Processing data: 5 ThreadId: 21540
Processing data: 6 ThreadId: 21696
Processing data: 7 ThreadId: 22976
Processing data: 8 ThreadId: 1172
Processing data: 9 ThreadId: 3212