[Python学习系列] Python进程与线程详解

线程

Python 多线程编程是一种在单个程序中同时执行多个线程的技术,主要用于提高程序的并发性和性能,尤其是在 I/O 操作频繁的场景下。Python 提供了 threading 模块来支持多线程编程。

基本概念

  • 线程:线程是一个独立的执行流,可以与其他线程并发运行。
  • 主线程:每个 Python 程序都有一个默认的主线程,程序从主线程开始运行。
  • 守护线程:守护线程在主线程结束时会自动退出,不会阻止程序终止。
  • Thread 类

    用于创建和管理线程。

    创建一个线程

    语法:

    threading.Thread(target, args=(), kwargs={}, daemon=None)

  • target: 线程执行的目标函数。
  • args: 传递给目标函数的参数(元组)。
  • kwargs: 传递给目标函数的关键字参数(字典)。
  • daemon: 设置为守护线程(布尔值)。
  • name: 设置线程名称。
  • 示例:

    import threading
    
    def print_numbers(max_num):
        print(f"线程名称:{threading.current_thread().name}")
        for i in range(1, max_num):
            print(i)
    
    def print_letters():
        print(f"线程名称:{threading.current_thread().name}")
        for letter in 'ABCDE':
            print(letter)
    
    # 创建线程
    # thread1 = threading.Thread(target=print_numbers, args=(6,))
    thread1 = threading.Thread(target=print_numbers, kwargs={'max_num': 6})
    thread2 = threading.Thread(target=print_letters)
    
    # 启动线程
    thread1.start()
    thread2.start()
    
    # 修改线程名称
    # thread2.name = "CustomThread2"
    
    # 等待所有线程完成
    thread1.join()
    thread2.join()
    
    print("所有线程执行完成")
    
  • start(): 启动线程并调用 run() 方法。
  • run(): 线程执行的代码,可以重写。
  • join(timeout=None): 阻塞主线程,直到调用 join 的线程结束或超时。
  • 线程之间是共享全局变量的

    import threading
    
    list1 = []
    
    def add_data():
        for i in range(3):
            list1.append(i)
            print(f"添加数据:{i}")
    
    def read_data():
        print(f"获取数据:{list1}")
    
    thread1 = threading.Thread(target=add_data)
    thread2 = threading.Thread(target=read_data)
    
    thread1.start()
    thread2.start()
    

    线程互斥 Lock

    线程共享数据会造成数据安全性问题。使用互斥锁解决。

    Lock 类:用于线程同步,防止多个线程同时访问共享资源。

    lock常用函数:

  • acquire(blocking=True, timeout=-1): 请求锁(加锁)。
  • release(): 释放锁。
  • import threading
    
    # 多个线程对全局变量进行自增
    g_num = 0
    
    # 创建一把互斥锁
    lock = threading.Lock()
    
    def task():
        global g_num
    
        # 对修改共享变量的代码进行加锁
        lock.acquire()  # 加锁
    
        for i in range(1000000):
            g_num += 1
        print(f"task {g_num}, 线程名称-{threading.current_thread().name}")
    
        # 共享变量操作完成后释放锁
        lock.release()  # 释放锁
    
    
    thread1 = threading.Thread(target=task)
    thread2 = threading.Thread(target=task)
    
    thread1.start()
    # thread1.join()    
    thread2.start()
    

    进程

    一个正在运行的程序就是一个进程,它是资源分配和执行的基本单位,每个进程有自己独立的内存空间、系统资源和执行线程。

    注意:一个程序运行后至少有一个进程,一个进程默认有一个线程,进程里面可以创建多个线程,线程是依附在进程里面的,没有进程就没有线程。

    python对进程的操作

    在 Python 中,可以使用 multiprocessing 模块来创建和管理进程。multiprocessing 模块允许你在多个处理器上运行任务,从而提高程序的性能。

    Process 类

    用于创建和管理进程。

    创建一个进程

    语法:

    multiprocessing.Process(target, args, kwargs, name, daemon)

  • target: 进程执行的目标函数。
  • args: 传递给目标函数的参数(元组)。
  • kwargs: 传递给目标函数的关键字参数(字典)。
  • daemon: 设置为守护进程(布尔值)。
  • name: 设置进程名称。
  • multiprocessing.Process的常用方法

  • start():启动进程并执行 target 函数。
  • join(timeout=None):等待进程终止,可选超时时间。
  • is_alive():返回进程是否正在运行。
  • terminate():立即终止进程。
  • 示例:

    import multiprocessing
    
    
    def department(num, name):
        print(f'员工 {num}, Name: {name}')
    
    
    if __name__ == '__main__':
        p = multiprocessing.Process(target=department, args=(5,), kwargs={'name': 'IT部门'})
        p.start()
    

    示例:获取进程名称和进程ID

    import multiprocessing
    import os
    import time
    
    
    def department(num, name):
        print(f'员工 {num}, Name: {name}')
    
        print(f"获取进程名称: {multiprocessing.current_process().name}")
        print(f"获取当前进程 ID: {os.getpid()}")
        print(f"获取父进程 ID: {os.getppid()}")
    
        while True:
            time.sleep(30)
    
    
    if __name__ == '__main__':
        p = multiprocessing.Process(target=department, args=(5,), kwargs={'name': 'IT部门'})
        p.start()
        print(f"获取Main进程名称: {multiprocessing.current_process().name}")
        print(f"获取Main进程 ID: {os.getpid()}")
        print(f"获取Main父进程 ID: {os.getppid()}")
    

    示例:杀死进程

    import multiprocessing
    import os
    import time
    
    
    def department(num, name):
        print(f'员工 {num}, Name: {name}')
    
        process_pid = os.getpid()
        print(f"获取当前进程 ID: {process_pid}")
        # 杀死进程,类似linux中的 kill -9 pid
        os.kill(process_pid, 9)
    
        while True:
            time.sleep(30)
    
    
    if __name__ == '__main__':
        p = multiprocessing.Process(target=department, args=(5,), kwargs={'name': 'IT部门'})
        p.start()
    

    注意:

  • 进程之间不共享全局变量。
  • 主进程会等待所有的子进程执行结束后再结束。
  • 进程内的异常无法通过 try-except 捕获到,需要使用 multiprocessing.ProcessProcess 对象的 join() 方法来获取异常
  • 进程之间共享数据

    multiprocessing.Queue()
    import multiprocessing
    
    
    # 生产者
    def producer(queue):
        for i in range(5):
            queue.put(i)
    
    
    # 消费者
    def consumer(queue):
        while True:
            item = queue.get()
            if item is None:  # 消费者退出循环条件
                break
            print(f"Got item: {item}")
    
    
    if __name__ == '__main__':
        queue = multiprocessing.Queue()
        p1 = multiprocessing.Process(target=producer, args=(queue,))
        p2 = multiprocessing.Process(target=consumer, args=(queue,))
    
        p1.start()
        p2.start()
    
        p1.join()
        queue.put(None)  # 设置消费者退出循环条件
        p2.join()
    

    进程互斥 Lock

    import multiprocessing
    import time
    
    
    # 多个进程调用这个函数,对共享变量数据进行操作
    def worker(lock, shared_value):
        for _ in range(10):
            # 获取锁, with 上下文写法,会自动释放锁资源
            with lock:
                # 临界区开始-锁开始
                temp = shared_value.value
                time.sleep(0.1)  # 模拟一些计算或操作
                shared_value.value = temp + 1
                # 临界区结束-锁结束
    
    
    if __name__ == "__main__":
        # 创建一把锁
        lock = multiprocessing.Lock()
        # 共享的整数变量,初始值为0
        shared_value = multiprocessing.Value('i', 0)
        processes = []
    
        # 创建多个进程
        for _ in range(5):
            p = multiprocessing.Process(target=worker, args=(lock, shared_value))
            processes.append(p)
            p.start()
    
        # 等待所有进程完成
        for p in processes:
            p.join()
    
        print(f"最终的 shared_counter 值: {shared_value.value}")
    

    作者:又逢乱世

    物联沃分享整理
    物联沃-IOTWORD物联网 » [Python学习系列] Python进程与线程详解

    发表回复