📜  Python中的多线程 |第 2 组(同步)(1)

📅  最后修改于: 2023-12-03 15:19:28.575000             🧑  作者: Mango

Python中的多线程 | 第 2 组(同步)

在并行计算中,多线程是一种广泛使用的技术。Python中的多线程模块是简单易用的,它提供了同步和非同步两种模式。

1. 同步多线程

同步多线程意味着线程的执行是有顺序的,也就是说在一个线程执行完成之前,其他线程的执行都会被阻塞。Python中的 threading 模块提供了一些同步机制,如锁、条件变量、信号量等。

1.1 锁

锁是最基本的同步机制之一。线程在访问共享资源之前会先请求获得锁,如果锁已经被其他线程获得了,那么当前线程会阻塞,直到锁被释放。

以下是一个简单的例子,其中两个线程并发地增加一个变量,使用锁可以保证操作的安全性。

import threading

def add_one(lock, count):
    for i in range(100000):
        lock.acquire()
        count += 1
        lock.release()
    print("add_one finished")

def add_two(lock, count):
    for i in range(100000):
        lock.acquire()
        count += 2
        lock.release()
    print("add_two finished")

def main():
    count = 0
    lock = threading.Lock()
    thread1 = threading.Thread(target=add_one, args=(lock, count))
    thread2 = threading.Thread(target=add_two, args=(lock, count))
    thread1.start()
    thread2.start()
    thread1.join()
    thread2.join()
    print(count)

if __name__ == '__main__':
    main()
1.2 条件变量

条件变量用于在线程之间共享状态信息,当一个线程需要等待某个条件满足时,它会阻塞并释放资源,直到另一个线程发出信号通知它条件已经满足。

以下是一个简单的例子,在线程1中当count的值达到1000时,唤醒线程2。

import threading

def wait_for_count(condition, count):
    with condition:
        condition.wait()
    print("wait_for_count finished, count=", count)

def increase_count(condition, count):
    for i in range(100):
        count += 1
        if count >= 1000:
            with condition:
                condition.notify_all()
        print("increase_count count=", count)
    print("increase_count finished, count=", count)

def main():
    count = 0
    condition = threading.Condition()
    thread1 = threading.Thread(target=wait_for_count, args=(condition, count))
    thread2 = threading.Thread(target=increase_count, args=(condition, count))
    thread1.start()
    thread2.start()
    thread1.join()
    thread2.join()
    print(count)

if __name__ == '__main__':
    main()
2. 非同步多线程

非同步多线程不需要保证线程的执行顺序,它们可以并发执行。进程中每个非同步线程将有自己的控制流和存储器状态。Python提供了一些非同步机制,如Event对象和队列。

2.1 Event对象

Event对象是一种简单的同步机制,它包括一个内部标志位和两种方法wait()和set()。当一个线程调用wait()方法时,如果标志位为False,该线程会被阻塞直到另一个线程调用set()方法把标志位设置为True。

以下是一个简单的例子,在线程2中等待线程1设置Event对象的标志位。

import threading

def wait_for_event(event):
    print("wait_for_event start")
    event.wait()
    print("event is set")

def set_event(event):
    print("set_event start")
    event.set()

def main():
    event = threading.Event()
    thread1 = threading.Thread(target=set_event, args=(event,))
    thread2 = threading.Thread(target=wait_for_event, args=(event,))
    thread1.start()
    thread2.start()
    thread1.join()
    thread2.join()

if __name__ == '__main__':
    main()
2.2 队列

队列可用于在线程之间传递信息和数据。Python提供了queue模块,它是线程安全的。

以下是一个简单的例子,其中一个线程将数字1-10放入队列中,另一个线程将它们取出并打印。

import queue
import threading

def producer(queue):
    for i in range(1, 11):
        queue.put(i)

def consumer(queue):
    while not queue.empty():
        print(queue.get())

def main():
    queue = queue.Queue()
    thread1 = threading.Thread(target=producer, args=(queue,))
    thread2 = threading.Thread(target=consumer, args=(queue,))
    thread1.start()
    thread2.start()
    thread1.join()
    thread2.join()

if __name__ == '__main__':
    main()
3. 总结

Python中的多线程模块提供了一些同步和非同步的多线程机制,在不同的场景下可以选择相应的方法。在使用多线程时,需要注意线程安全问题,避免出现数据竞争等问题,从而保证程序的正确性。