Python threading的使用方法解析

  • Post category:Python

Python threading的使用方法解析

什么是线程?

线程是指在单个程序内执行的一系列并发执行的控制流,每个线程都有自己的代码执行路径、程序计数器和栈。在一个进程内,多个线程可共享同一内存地址空间。

基本语法

在Python中,使用threading库可方便地实现线程功能。

创建线程:

import threading 

def my_thread():
    print("this is my thread")

if __name__ == "__main__":
    t = threading.Thread(target=my_thread)

启动线程:

t.start()

阻塞主线程直到所有子线程完成:

t.join()

结束线程:

threading.Thread._stop()

线程同步

在线程之间共享变量时,可能会发生数据竞争问题。为避免此问题,可以使用线程同步。

互斥锁(Mutex)

互斥锁可用来保护共享变量不被多个线程同时修改。

mutex = threading.Lock()
mutex.acquire()
# access shared data
mutex.release()

信号量(Semaphore)

信号量的作用是将并行性降级为串行性。它用来控制同时访问某个资源的用户数。

semaphore = threading.Semaphore(3)
semaphore.acquire()
# access shared data
semaphore.release()

条件(Condition)

条件是多线程编程中最常见的同步原语之一。每个条件都与一个锁对象关联,同时具有一个等待列表。当线程调用条件的等待方法之一时,它会将线程放置到列表中并释放锁。当前等待列表上的线程,在条件或者超时时,会重新获取锁并继续执行。

condition = threading.Condition()
condition.acquire()
# access shared data
condition.notify()
condition.release()

示例说明

示例1: 使用互斥锁

import threading

class Counter:
    def __init__(self):
        self.value = 0
        self.mutex = threading.Lock()

    def increment(self):
        self.mutex.acquire()
        self.value += 1
        self.mutex.release()

def update(counter):
    for i in range(10000):
        counter.increment()

def main():
    counter = Counter()
    threads = []
    for i in range(10):
        threads.append(threading.Thread(target=update, args=(counter,)))
        threads[-1].start()
    for t in threads:
        t.join()
    print(counter.value)

main()

示例2: 使用条件同步

import threading

class Worker:
    def __init__(self):
        self.queue = []
        self.condition = threading.Condition()

    def produce(self):
        with self.condition:
            while len(self.queue) > 0:
                self.condition.wait()
            print('Producing Item')
            self.queue.append(1)
            self.condition.notify_all()

    def consume(self):
        with self.condition:
            while len(self.queue) == 0:
                self.condition.wait()
            print('Consuming Item')
            self.queue.pop(0)
            self.condition.notify_all()

def worker_thread(worker, is_producer):
    for i in range(10):
        if is_producer:
            worker.produce()
        else:
            worker.consume()

def main():
    worker = Worker()
    threads = []
    threads.append(threading.Thread(target=worker_thread, args=(worker, True)))
    threads.append(threading.Thread(target=worker_thread, args=(worker, False)))
    for t in threads:
        t.start()
    for t in threads:
        t.join()

main()

以上两个示例展示了线程同步中的互斥锁和条件同步的用法。在示例1中,组合使用互斥锁和计数器,保证了多个线程修改计数器时不会出现数据竞争问题。在示例2中,演示了生产者消费者模型中的条件同步。多个线程共同修改队列时,使用条件同步方式保证生产者在队列为空时才能生产,消费者在队列非空时才能消费,避免线程安全问题的同时提高了程序的效率。