Python 简明教程
Python - Synchronizing Threads
在 Python 中,当多个线程同时使用共享资源时,同步其访问以维护数据完整性和程序正确性非常重要。可以利用 threading 模块提供的各种同步原语在 Python 中同步线程,例如锁、条件、信号量和屏障来控制对共享资源的访问并协调多个线程的执行。
In Python, when multiple threads are working concurrently with shared resources, it’s important to synchronize their access to maintain data integrity and program correctness. Synchronizing threads in python can be achieved using various synchronization primitives provided by the threading module, such as locks, conditions, semaphores, and barriers to control access to shared resources and coordinate the execution of multiple threads.
在本教程中,我们将学习 Python 的 threading 模块提供的各种同步原语。
In this tutorial, we’ll learn about various synchronization primitives provided by Python’s threading module.
Thread Synchronization using Locks
Python 的线程模块中的锁对象提供了最简单的同步原语。它们允许线程获取和释放关键代码段周围的锁,确保一次只有一个线程可以执行受保护的代码。
The lock object in the Python’s threading module provide the simplest synchronization primitive. They allow threads to acquire and release locks around critical sections of code, ensuring that only one thread can execute the protected code at a time.
通过调用 Lock() 方法创建一个新锁,该方法返回一个锁对象。可以使用 acquire(blocking) 获取锁,该方法强制线程同步运行。可选的 blocking 参数允许您控制线程是否等待获取锁,以及是否使用 release() 方法释放。
A new lock is created by calling the Lock() method, which returns a lock object. The lock can be acquired using the acquire(blocking) method, which force the threads to run synchronously. The optional blocking parameter enables you to control whether the thread waits to acquire the lock and released using the release() method.
Example
以下示例演示如何使用锁(threading.Lock() 方法)在 Python 中同步线程,确保多个线程安全正确地访问共享资源。
The following example demonstrates how to use locks (the threading.Lock() method) to synchronize threads in Python, ensuring that multiple threads access shared resources safely and correctly.
import threading
counter = 10
def increment(theLock, N):
global counter
for i in range(N):
theLock.acquire()
counter += 1
theLock.release()
lock = threading.Lock()
t1 = threading.Thread(target=increment, args=[lock, 2])
t2 = threading.Thread(target=increment, args=[lock, 10])
t3 = threading.Thread(target=increment, args=[lock, 4])
t1.start()
t2.start()
t3.start()
# Wait for all threads to complete
for thread in (t1, t2, t3):
thread.join()
print("All threads have completed")
print("The Final Counter Value:", counter)
Condition Objects for Synchronizing Python Threads
条件变量允许线程等到另一个线程通知后才继续执行。它们对于提供 communication between the threads 非常有用。 wait() 方法用于在另一个线程通过 notify() 或 notify_all() 通知一个线程之前阻塞该线程。
Condition variables enable threads to wait until notified by another thread. They are useful for providing communication between the threads. The wait() method is used to block a thread until it is notified by another thread through notify() or notify_all().
Example
此示例演示了条件对象如何使用 notify() 和 wait() 方法同步线程。
This example demonstrates how Condition objects can synchronize threads using the notify() and wait() methods.
import threading
counter = 0
# Consumer function
def consumer(cv):
global counter
with cv:
print("Consumer is waiting")
cv.wait() # Wait until notified by increment
print("Consumer has been notified. Current Counter value:", counter)
# increment function
def increment(cv, N):
global counter
with cv:
print("increment is producing items")
for i in range(1, N + 1):
counter += i # Increment counter by i
# Notify the consumer
cv.notify()
print("Increment has finished")
# Create a Condition object
cv = threading.Condition()
# Create and start threads
consumer_thread = threading.Thread(target=consumer, args=[cv])
increment_thread = threading.Thread(target=increment, args=[cv, 5])
consumer_thread.start()
increment_thread.start()
consumer_thread.join()
increment_thread.join()
print("The Final Counter Value:", counter)
Synchronizing threads using the join() Method
Python 的线程模块中的 join() 方法用于等到所有线程执行完成为止。这是同步主线程与其他线程完成执行的一种简单方法。
The join() method in Python’s threading module is used to wait until all threads have completed their execution. This is a straightforward way to synchronize the main thread with the completion of other threads.
Example
这通过使用 join() 方法演示线程同步,以确保主线程等待所有已启动线程完成其工作后再继续执行。
This demonstrates synchronization of threads using the join() method to ensure that the main thread waits for all started threads to complete their work before proceeding.
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)
print_time(self.name, self.counter, 3)
def print_time(threadName, delay, counter):
while counter:
time.sleep(delay)
print("%s: %s" % (threadName, time.ctime(time.time())))
counter -= 1
threads = []
# Create new threads
thread1 = MyThread(1, "Thread-1", 1)
thread2 = MyThread(2, "Thread-2", 2)
# Start the new Threads
thread1.start()
thread2.start()
# Join the threads
thread1.join()
thread2.join()
print("Exiting Main Thread")
Output
在执行上述程序后,它将生成以下输出 −
On executing the above program, it will produce the following output −
Starting Thread-1
Starting Thread-2
Thread-1: Mon Jul 1 16:05:14 2024
Thread-2: Mon Jul 1 16:05:15 2024
Thread-1: Mon Jul 1 16:05:15 2024
Thread-1: Mon Jul 1 16:05:16 2024
Thread-2: Mon Jul 1 16:05:17 2024
Thread-2: Mon Jul 1 16:05:19 2024
Exiting Main Thread
Additional Synchronization Primitives
除了上述同步基元之外,Python 的线程模组还提供:
In addition to the above synchronization primitives, Python’s threading module offers: −
-
RLocks (Reentrant Locks): A variant of locks that allow a thread to acquire the same lock multiple times before releasing it, useful in recursive functions or nested function calls.
-
*Semaphores:*Similar to locks but with a counter. Threads can acquire the semaphore up to a certain limit defined during initialization. Semaphores are useful for limiting access to resources with a fixed capacity.
-
Barriers: Allows a fixed number of threads to synchronize at a barrier point and continue executing only when all threads have reached that point. Barriers are useful for coordinating a group of threads that must all complete a certain phase of execution before any of them can proceed further.