天天看点

Python并发编程之线程实现方式

作者:风趣生命的起源

在Python中,线程(Thread)是一种轻量级的执行单元,可以并发执行多个线程,每个线程独立执行任务。线程是操作系统中调度和执行任务的基本单位,它可以与其他线程共享进程的资源和内存空间。

Python并发编程之线程实现方式

Python线程基本实现

Python提供了内置的`threading`模块,用于创建和管理线程。使用`threading`模块可以创建新的线程对象,并通过调用线程对象的`start()`方法来启动线程的执行。线程对象可以执行任意的可调用对象(如函数、方法等)作为线程的任务,通过定义这些任务可以实现并发执行的功能。

下面是一个简单的线程示例:

import threading
import time

def print_numbers():
    for i in range(5):
        print(f"Thread 1: {i}")
        time.sleep(1)

def print_letters():
    for letter in "ABCDE":
        print(f"Thread 2: {letter}")
        time.sleep(1)

# 创建线程对象
thread1 = threading.Thread(target=print_numbers)
thread2 = threading.Thread(target=print_letters)

# 启动线程
thread1.start()
thread2.start()

# 等待线程执行完毕
thread1.join()
thread2.join()

print("Main thread exiting.")           

在上述示例中,我们定义了两个函数`print_numbers()`和`print_letters()`,分别用于打印数字和字母。然后,我们创建了两个线程对象`thread1`和`thread2`,并分别指定线程的任务函数。接着,通过调用`start()`方法来启动线程的执行。最后,使用`join()`方法等待线程执行完毕,确保主线程在所有线程完成后退出。

运行以上代码,你将看到类似以下的输出:

Thread 1: 0
Thread 2: A
Thread 1: 1
Thread 2: B
Thread 1: 2
Thread 2: C
Thread 1: 3
Thread 2: D
Thread 1: 4
Thread 2: E
Main thread exiting.           

可以看到,两个线程交替执行,每个线程执行一次任务后暂停一秒,然后切换到另一个线程执行。这样就实现了简单的并发执行。

需要注意的是,线程之间的切换是由操作系统的线程调度器控制的,所以线程的执行顺序可能会有不确定性。因此,在使用线程时,需要考虑线程间的同步和互斥,以避免并发访问共享资源导致的问题。

Python线程同步方式

在Python中,为了保证多线程环境下的线程安全性,可以使用各种同步机制和工具来实现线程间的同步和互斥。下面是几种常见的Python线程安全同步的方式的示例:

1. 互斥锁(Lock):

```python

import threading

# 创建互斥锁对象

import threading

# 创建互斥锁对象
lock = threading.Lock()

shared_resource = 0

def increment():
    global shared_resource
    for _ in range(100000):
        # 获取互斥锁
        lock.acquire()
        shared_resource += 1
        # 释放互斥锁
        lock.release()

# 创建多个线程来调用increment函数
threads = []
for _ in range(5):
    t = threading.Thread(target=increment)
    threads.append(t)
    t.start()

# 等待所有线程执行完毕
for t in threads:
    t.join()

print("Result:", shared_resource)           

上述示例中,使用`threading.Lock()`创建了一个互斥锁对象`lock`。在`increment()`函数中,通过调用`lock.acquire()`获取互斥锁,执行临界区代码,然后使用`lock.release()`释放互斥锁。这样可以确保每次只有一个线程可以访问临界区,从而保证线程安全。

2. 信号量(Semaphore):

import threading

# 创建信号量对象
semaphore = threading.Semaphore(2)

def task():
    # 请求信号量
    semaphore.acquire()
    try:
        # 临界区代码
        print("Executing task")
    finally:
        # 释放信号量
        semaphore.release()

# 创建多个线程来调用task函数
threads = []
for _ in range(5):
    t = threading.Thread(target=task)
    threads.append(t)
    t.start()

# 等待所有线程执行完毕
for t in threads:
    t.join()           

在上述示例中,使用`threading.Semaphore(2)`创建了一个信号量对象`semaphore`,并设置初始值为2。在`task()`函数中,通过调用`semaphore.acquire()`请求信号量,执行临界区代码,然后使用`semaphore.release()`释放信号量。信号量的初始值为2,因此最多允许两个线程同时进入临界区,其他线程需要等待。

3. 条件变量(Condition):

import threading

# 创建条件变量对象
condition = threading.Condition()

queue = []

def producer():
    with condition:
        # 生产者线程等待条件满足
        while len(queue) >= 5:
            condition.wait()
        # 生产者线程向队列中添加元素
        item = "Item"
        queue.append(item)
        print("Produced:", item)
        # 通知消费者线程
        condition.notify()

def consumer():
    with condition:
        # 消费者线程等待条件满足
        while len(queue) == 0:
            condition.wait()
        # 消费者线程从队列中取出元素           

总结

线程是一种用于并发执行任务的执行单元,Python的`threading`模块提供了创建和管理线程的功能。通过创建线程对象,并指定线程的任务函数,可以实现多个线程的并发执行。但需要注意线程间的同步和互斥,以确保线程安全。