Multiprocessing in Python

Introduction

Multiprocessing in Python

Processes in Python

from multiprocessing import Process
import time

def print_numbers():
    for i in range(10):
        time.sleep(1)
        print(i)

def print_letters():
    for letter in 'abcdefghij':
        time.sleep(1)
        print(letter)

if __name__ == '__main__':
    process1 = Process(target=print_numbers)
    process2 = Process(target=print_letters)

    process1.start()
    process2.start()

    process1.join() #  join method is used to wait for the process to finish
    process2.join()


------
$ python a.py 
0
a
b
1
c
2
d
3
e
4
5
f
g
6
h
7
8
i
j
9

Inter-Process Communication

The multiprocessing module in Python provides various tools for inter-process communication, including pipes and queues. Below is an example demonstrating communication between the main process and a child process.

from multiprocessing import Process, Queue

def worker(q):
    q.put('Hello, world!')

def main():
    q = Queue()
    p = Process(target=worker, args=(q,))
    p.start()
    print(q.get())
    p.join()

if __name__ == '__main__':
    main()

---
$ python a.py 
Hello, world!

Process Synchronization

The multiprocessing module in Python provides various tools for process synchronization, including locks and semaphores.

from multiprocessing import Process, Lock, Value
import time
import random

def worker(lock, shared_counter):
    """Child process task: modify the shared counter after acquiring the lock"""
    process_name = f"Process-{Process().name}"

    # Simulate random time-consuming operation (non-critical section)
    time.sleep(random.uniform(0.1, 0.5))

    # Use with statement to automatically acquire and release the lock (recommended)
    with lock:
        print(f"{process_name} entered critical section")

        # ---- Critical section begins ----
        current_value = shared_counter.value
        time.sleep(0.1)  # Simulate time-consuming operation (amplifying race condition)
        shared_counter.value = current_value + 1
        print(f"{process_name} modified counter: {current_value} -> {shared_counter.value}")
        # ---- Critical section ends ----

if __name__ == '__main__':
    # Create a shared counter (initial value=0) and a process lock
    counter = Value('i', 0)  # 'i' indicates a signed integer
    process_lock = Lock()

    # Create and start 5 processes
    processes = []
    for i in range(5):
        p = Process(target=worker, args=(process_lock, counter))
        processes.append(p)
        p.start()

    # Wait for all processes to complete
    for p in processes:
        p.join()

    # Verify result (should be 5 in correct cases)
    print(f"\nFinal counter value: {counter.value} (expected value: 5)")

---
$ python a.py 
Process-Process-2:1 entered critical section
Process-Process-2:1 modified counter: 0 -> 1
Process-Process-1:1 entered critical section
Process-Process-1:1 modified counter: 1 -> 2
Process-Process-5:1 entered critical section
Process-Process-5:1 modified counter: 2 -> 3
Process-Process-3:1 entered critical section
Process-Process-3:1 modified counter: 3 -> 4
Process-Process-4:1 entered critical section
Process-Process-4:1 modified counter: 4 -> 5

Final counter value: 5 (expected value: 5)

Process Pool

We can use the multiprocessing.Pool class to create a pool of processes. The number of processes in the pool is fixed, and when a new task is submitted to the pool, if there are idle processes, one will be assigned to the task. If all processes are busy, the task will wait until a process becomes idle.

from multiprocessing import Pool

def square(x):
    return x * x

if __name__ == '__main__':
    with Pool(5) as p:
        print(p.map(square, [1, 2, 3, 4, 5]))


---
$ python a.py 
[1, 4, 9, 16, 25]

I have a bold idea: every technical article I post has been personally verified to ensure current usability. I welcome friends to practice along; if you encounter issues, feel free to leave a message; or if you have technical difficulties, let me know, and I will verify and experiment. Let’s improve together and achieve mutual success!!!

Multiprocessing in PythonRecommended HighlightsChina’s first free one-core one-G cloud server?The secrets that Linux veterans won’t tell: why tar.gz crushes zip and 7z?Highly recommended, 5 must-have productivity software for computersTested, an incredibly useful Linux connection tool, no less than xshll magic

Leave a Comment