Python and multi-threading. Is it a good idea?



No, it is not a good idea. Multithreading is not possible in Python due to something called the Global Interpreter Lock. A multi-threaded program contains two or more parts that can run concurrently and each part can handle a different task at the same time making optimal use of the available resources specially when your computer has multiple CPUs. Multi-threading enables you to write in a way where multiple activities can proceed concurrently in the same program.

Python doesn't allow multi-threading, but if you want to run your program at a speed that needs to wait for something like IO, then it's used a lot. whereas the threading package couldn't let you use extra CPU cores. Python doesn't support multi-threading because Python on the Cpython interpreter does not support true multi-core execution via multithreading. However, Python does have a threading library.

The GIL does not prevent threading. All the GIL does is make sure only one thread is executing Python code at a time; control still switches between threads. However, if you mix in C extensions and I/O (such as PIL or numpy operations), any C code can run in parallel with one active Python thread.

The threading Module

We can still perform multi-threading using the threading module. Multiple threads within a process share the same data space with the main thread and can therefore share information or communicate with each other more easily than if they were separate processes.

The newer threading module included with Python 2.4 provides much more powerful, high-level support for threads than the thread module discussed in the previous section.

The threading module exposes all the methods of the thread module and provides some additional methods −

  • threading.activeCount() − Returns the number of thread objects that are active.

  • threading.currentThread() − Returns the number of thread objects in the caller's thread control.

  • threading.enumerate() − Returns a list of all thread objects that are currently active.

The threading module has the Thread class that implements threading. The methods provided by the Thread class are as follows −

  • run() − The run() method is the entry point for a thread.

  • start() − The start() method starts a thread by calling the run method.

  • join([time]) − The join() waits for threads to terminate.

  • isAlive() − The isAlive() method checks whether a thread is still executing.

  • getName() − The getName() method returns the name of a thread.

  • setName() − The setName() method sets the name of a thread.

Example

The threading module provided with Python includes a simple-to-implement locking mechanism that allows you to synchronize threads. A new lock is created by calling the Lock() method, which returns the new lock.

The acquire(blocking) method of the new lock object is used to force the threads to run synchronously. The optional blocking parameter enables you to control whether the thread waits to acquire the lock.

If blocking is set to 0, the thread returns immediately with a 0 value if the lock cannot be acquired and with a 1 if the lock was acquired. If blocking is set to 1, the thread blocks and wait for the lock to be released.

The release() method of the new lock object is used to release the lock when it is no longer required.

import threading import time class myThread (threading.Thread): def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): print ("Starting " + self.name) # Get lock to synchronize threads threadLock.acquire() print_time(self.name, self.counter, 3) # Free lock to release next thread threadLock.release() def print_time(threadName, delay, counter): while counter: time.sleep(delay) print ("%s: %s" % (threadName, time.ctime(time.time()))) counter -= 1 threadLock = threading.Lock() threads = [] # Create new threads thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2) # Start new Threads thread1.start() thread2.start() # Add threads to thread list threads.append(thread1) threads.append(thread2) # Wait for all threads to complete for t in threads: t.join() print ("Exiting Main Thread")

Output

Starting Thread-1
Starting Thread-2
Thread-1: Fri Aug 12 05:49:52 2022
Thread-1: Fri Aug 12 05:49:53 2022
Thread-1: Fri Aug 12 05:49:54 2022
Thread-2: Fri Aug 12 05:49:56 2022
Thread-2: Fri Aug 12 05:49:58 2022
Thread-2: Fri Aug 12 05:50:00 2022
Exiting Main Thread

Advertisements