python多线程抽象编程模型详解

  

Python多线程抽象编程模型详解

概述

多线程编程是指在同一时间内,有多个线程在同时执行。Python中常用的多线程模块是threading

在多线程编程中,有两种常见的编程模型,即抢占式协作式,Python采用的是协作式的多线程编程模型。

表示线程

在Python中,线程用threading.Thread类表示,创建线程需要实现run方法,此方法中包含线程要执行的代码。

import threading
import time

class MyThread(threading.Thread):
    def __init__(self, num):
        threading.Thread.__init__(self)
        self.num = num

    def run(self):
        print("Thread {} started".format(self.num))
        time.sleep(1)
        print("Thread {} stopped".format(self.num))

thread1 = MyThread(1)
thread2 = MyThread(2)
thread1.start()
thread2.start()

创建线程

在Python中创建线程有三种方式,分别是:

  • 使用threading.Thread类创建线程
  • 使用threading.Thread子类化创建线程
  • 使用_thread模块创建线程

使用threading.Thread类创建线程

这是Python中最常见的创建线程的方式。

import threading
import time

def print_time(thread_name, delay):
    count = 0
    while count < 5:
        time.sleep(delay)
        count += 1
        print("{}: {}".format(thread_name, time.ctime(time.time())))

thread1 = threading.Thread(target=print_time, args=("Thread 1", 2))
thread2 = threading.Thread(target=print_time, args=("Thread 2", 4))
thread1.start()
thread2.start()

使用threading.Thread子类化创建线程

这种方式需要继承并重写threading.Thread类。

import threading
import time

class MyThread(threading.Thread):
    def __init__(self, thread_name, delay):
        threading.Thread.__init__(self)
        self.thread_name = thread_name
        self.delay = delay

    def run(self):
        count = 0
        while count < 5:
            time.sleep(self.delay)
            count += 1
            print("{}: {}".format(self.thread_name, time.ctime(time.time())))

thread1 = MyThread("Thread 1", 2)
thread2 = MyThread("Thread 2", 4)
thread1.start()
thread2.start()

使用_thread模块创建线程

这种方式与threading.Thread类似,但是使用起来相对比较困难,需要直接使用_thread模块的函数。

import _thread
import time

def print_time(thread_name, delay):
    count = 0
    while count < 5:
        time.sleep(delay)
        count += 1
        print("{}: {}".format(thread_name, time.ctime(time.time())))

try:
    _thread.start_new_thread(print_time, ("Thread 1", 2))
    _thread.start_new_thread(print_time, ("Thread 2", 4))
except:
    print("Error: 无法启动线程")

线程同步

在多线程编程中,为了避免线程之间的互相协调和访问共享资源发生冲突,需要采用线程同步技术。

常用的线程同步技术有:

  • 互斥锁(mutex):一个线程用完临界资源后释放锁,其他等待访问此资源的线程进入临界区执行。
  • 信号量(semaphore):同mutex,不过有多个锁。临界区内最多只能同时运行有限数量的线程。
  • 事件(event):一根线程A触发了一个事件a,另一个线程B可以等待这个事件的发生,并接收该事件发出的信息,从而达到两个线程之间的通信。

互斥锁

互斥锁使用threading.Lock对象实现,可以确保线程互不干扰地访问共享资源。

import threading
import time

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

    def increment(self):
        self.lock.acquire()
        try:
            self.value += 1
        finally:
            self.lock.release()

def update_counter(counter):
    for i in range(5):
        time.sleep(0.5)
        counter.increment()
    print("Counter's total value is: {}".format(counter.value))

counter = Counter()
thread1 = threading.Thread(target=update_counter, args=(counter,))
thread2 = threading.Thread(target=update_counter, args=(counter,))
thread1.start()
thread2.start()

信号量

信号量使用threading.Semaphore实现,可以设置允许访问的线程数量。

import threading
import time

class Test:
    def __init__(self, sem):
        self.sem = sem

    def method(self):
        self.sem.acquire()
        print("当前线程:{}".format(threading.current_thread().name))
        time.sleep(1)
        self.sem.release()

sem = threading.Semaphore(3)
tests = [Test(sem) for i in range(10)]
threads = [threading.Thread(target=test.method) for test in tests]
for thread in threads:
    thread.start()
for thread in threads:
    thread.join()

事件

事件使用threading.Event实现。

import threading
import time

class EventTest:
    def __init__(self, event):
        self.event = event

    def wait_for_event(self):
        print("{} 开始等待事件".format(threading.current_thread().name))
        self.event.wait()
        print("{} 收到事件".format(threading.current_thread().name))

    def send_event(self):
        print("事件马上要处理")
        time.sleep(2)
        print("事件处理完毕")
        self.event.set()

event = threading.Event()
tests = [EventTest(event) for i in range(2)]
threads = [threading.Thread(target=test.wait_for_event) for test in tests] + [threading.Thread(target=test.send_event) for test in tests]
for thread in threads:
    thread.start()
for thread in threads:
    thread.join()

总结

本文详细介绍了Python多线程抽象编程模型。首先讲解了线程的表示,其次讲解了创建线程的三种方式,接着介绍了线程同步,包括互斥锁、信号量和事件。最后进行了总结,并给出了两个示例说明。

相关文章