Python进阶(第四章: 多任务编程)

110 阅读7分钟

了解和掌握多任务、进程、多进程、获取进程编号、进程执行带参数的任务、线程、多线程、线程传参、线程注意点、线程同步、互斥锁、死锁、进程和线程对比、GIL、协程和协程的使用是多线程编程中的重要知识点。下面我将为每个知识点提供详细解释和示例代码。

1. 多任务

概念:多任务是计算机同时执行多个任务的能力。它可以是多进程或多线程的形式,允许程序同时执行多个任务,提高效率和性能。

2. 进程概念

概念:进程是操作系统中的一个独立执行单元,拥有独立的内存空间、代码和数据。每个进程都运行在自己的虚拟内存中,相互之间不共享内存。

3. 多进程的使用

示例:下面是一个使用Python的multiprocessing模块创建多进程的示例。该示例创建两个子进程,并分别执行不同的任务。

import multiprocessing
​
def task1():
    print("子进程1执行任务")
​
def task2():
    print("子进程2执行任务")
​
if __name__ == "__main__":
    process1 = multiprocessing.Process(target=task1)
    process2 = multiprocessing.Process(target=task2)
​
    process1.start()
    process2.start()
​
    process1.join()
    process2.join()
​
    print("主进程结束")

4. 获取进程编号

示例:在多进程编程中,您可以使用os模块来获取当前进程的编号。

import os
​
def get_process_id():
    return os.getpid()
​
if __name__ == "__main__":
    process_id = get_process_id()
    print(f"当前进程编号:{process_id}")

5. 进程执行带参数的任务

示例:您可以使用multiprocessing模块将参数传递给子进程。

import multiprocessing
​
def task_with_args(arg1, arg2):
    print(f"子进程执行任务,参数1:{arg1},参数2:{arg2}")
​
if __name__ == "__main__":
    process = multiprocessing.Process(target=task_with_args, args=("参数1值", "参数2值"))
    process.start()
    process.join()

6. 线程的概念

概念:线程是进程内的执行单元,多个线程共享同一个进程的内存空间。它们可以并发执行,提高程序的响应速度。

7. 多线程的使用

示例:下面是一个使用Python的threading模块创建多线程的示例。该示例创建两个线程,并分别执行不同的任务。

import threading
​
def task1():
    print("线程1执行任务")
​
def task2():
    print("线程2执行任务")
​
if __name__ == "__main__":
    thread1 = threading.Thread(target=task1)
    thread2 = threading.Thread(target=task2)
​
    thread1.start()
    thread2.start()
​
    thread1.join()
    thread2.join()
​
    print("主线程结束")

8. 线程传参

示例:您可以使用threading模块将参数传递给线程。

import threading
​
def task_with_args(arg1, arg2):
    print(f"线程执行任务,参数1:{arg1},参数2:{arg2}")
​
if __name__ == "__main__":
    thread = threading.Thread(target=task_with_args, args=("参数1值", "参数2值"))
    thread.start()
    thread.join()

9. 线程注意点

  • 线程之间共享进程的内存,需要谨慎处理共享数据,避免数据竞争和不同步问题。
  • Python的全局解释器锁(GIL)可以限制多线程并发执行,因此多线程并不一定能提高CPU密集型任务的性能。

10. 线程同步解决资源竞争问题

示例:使用threading模块的锁对象来实现线程同步,确保多个线程安全地访问共享资源。

import threading
​
shared_variable = 0
lock = threading.Lock()
​
def increment_shared_variable():
    global shared_variable
    with lock:
        shared_variable += 1if __name__ == "__main__":
    threads = [threading.Thread(target=increment_shared_variable) for _ in range(10)]
​
    for thread in threads:
        thread.start()
​
    for thread in threads:
        thread.join()
​
    print(f"共享变量的值:{shared_variable}")

11. 互斥锁

概念:互斥锁是一种同步机制,它可以确保在任何时刻只有一个线程能够访问共享资源。在Python中,您可以使用threading模块的Lock对象来实现互斥锁。

12. 死锁

概念:死锁是多线程编程中的常见问题,它发生在两个或多个线程无限期地等待彼此释放资源的情况下。死锁可以通过良好的设计和资源管理来避免。

13. 进程和线程对比

对比

  • 进程是独立的执行单元,各自有独立的内存空间,通信需要使用IPC(Inter-Process Communication)机制。
  • 线程是进程内的执行单元,共享进程的内存空间,通信更容易。

14. GIL(全局解释器锁)

概念:GIL是Python的一个特性,它限制了多线程并发执行,只允许一个线程执行Python字节码。这意味着多线程不能利用多核处理器提高性能。

15. 协程

概念:协程是一种轻量级的并发机制,允许在同一个线程中实现多个执行流,提高效率。Python的asyncio库用于实现协程。

16. 协程的使用

示例:下面是一个使用Python的asyncio库创建协程的示例。该示例定义了一个异步函数并使用事件循环来执行协程任务。

import asyncio
​
async def task():
    print("协程任务开始")
    await asyncio.sleep(2)
    print("协程任务结束")
​
if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(task())
    loop.close()

这些知识点涵盖了多线程和多进程编程的关键概念和使用方法。多线程和多进程编程在提高程序性能和并发性方面都非常重要,但也需要小心处理共享资源和同步问题。了解这些概念并掌握它们的使用方法将有助于编写高效且可靠的多任务应用程序。

18. 商业案例:在线购物网站的库存管理系统

假设您正在开发一个在线购物网站,需要一个复杂的库存管理系统,以确保商品的库存和订单处理得以有效进行。这个系统包括以下功能:

  1. 创建商品库存列表(多进程)
  2. 处理订单并减少库存(多线程)
  3. 监视库存并自动补充(线程同步、互斥锁)
  4. 使用协程进行高并发处理订单

以下是这个系统的代码示例:

import multiprocessing
import threading
import asyncio
import random
import time
​
# 商品库存列表
inventory = {'product1': 100, 'product2': 50, 'product3': 200}
lock = threading.Lock()
​
# 1. 创建商品库存列表
def create_inventory(product_name, quantity):
    global inventory
    with lock:
        inventory[product_name] = quantity
    print(f"创建库存:{product_name} - {quantity}")
​
# 2. 处理订单并减少库存
def process_order(order):
    global inventory
    product_name, quantity = order
    with lock:
        if product_name in inventory and inventory[product_name] >= quantity:
            inventory[product_name] -= quantity
            print(f"处理订单:{product_name} - {quantity},库存剩余:{inventory[product_name]}")
        else:
            print(f"订单失败:{product_name} - {quantity},库存不足")
​
# 3. 监视库存并自动补充
def auto_restock():
    global inventory
    while True:
        time.sleep(5)
        with lock:
            for product_name in inventory:
                if inventory[product_name] < 100:  # 补充库存到100
                    inventory[product_name] = 100
                    print(f"自动补充库存:{product_name} - 100")
​
# 4. 使用协程进行高并发处理订单
async def process_orders_coroutine(orders):
    tasks = []
    for order in orders:
        task = asyncio.create_task(process_order_coroutine(order))
        tasks.append(task)
    await asyncio.gather(*tasks)
​
async def process_order_coroutine(order):
    product_name, quantity = order
    await asyncio.sleep(random.uniform(0.1, 0.5))  # 模拟处理时间
    process_order(order)
​
if __name__ == "__main__":
    # 1. 创建商品库存列表(多进程)
    process1 = multiprocessing.Process(target=create_inventory, args=('product1', 100))
    process2 = multiprocessing.Process(target=create_inventory, args=('product2', 50))
    process3 = multiprocessing.Process(target=create_inventory, args=('product3', 200))
​
    process1.start()
    process2.start()
    process3.start()
​
    process1.join()
    process2.join()
    process3.join()
​
    # 2. 处理订单并减少库存(多线程)
    orders = [('product1', 10), ('product2', 20), ('product3', 30)]
    threads = [threading.Thread(target=process_order, args=(order,)) for order in orders]
​
    for thread in threads:
        thread.start()
​
    for thread in threads:
        thread.join()
​
    # 3. 监视库存并自动补充(线程同步、互斥锁)
    restock_thread = threading.Thread(target=auto_restock)
    restock_thread.daemon = True
    restock_thread.start()
​
    # 4. 使用协程进行高并发处理订单
    asyncio.run(process_orders_coroutine(orders))

在这个复杂的商业案例中,我们模拟了一个在线购物网站的库存管理系统,包括多进程创建库存、多线程处理订单、线程同步的库存监视和互斥锁,以及使用协程实现高并发订单处理。这个系统涵盖了多任务、进程、多进程的使用、获取进程编号、进程执行带参数的任务、线程、多线程的使用、线程传参、线程注意点、线程同步、互斥锁、死锁、进程和线程对比、GIL、协程和协程的使用的所有知识点。