【PYTHON 进程\线程\协程】

进程和线程的区别

线程和进程是操作系统中的两个核心概念。

进程是操作系统中的一个执行单元,它拥有独立的地址空间、内存、文件描述符、信号处理器等资源。每个进程都是由一个或多个线程组成的,每个线程都运行在进程的上下文中,共享进程的资源。

线程是进程中的一个执行单元,它拥有独立的栈、程序计数器和状态。线程是轻量级的执行单元,它可以与其他线程共享进程的资源,包括内存、文件描述符、信号处理器等。

因此,进程和线程的主要区别在于它们拥有的资源不同。进程拥有独立的资源,每个进程都需要进行上下文切换,这会导致开销较大;而线程共享进程的资源,因此线程的上下文切换开销相对较小,可以更高效地利用系统资源。另外,由于线程共享进程的地址空间,因此线程之间的通信和同步更加容易。

总的来说,线程和进程都是操作系统中的重要概念,它们各自有自己的优缺点,应根据具体的应用场景选择合适的方式来实现并发编程。

线程

在Python中,可以使用threading模块来实现多线程编程。以下是一个简单的示例代码,演示如何使用Python的threading模块创建和启动线程:

import threading

def worker():
    """线程执行的任务"""
    print('Worker thread started')
    # 执行任务
    print('Worker thread finished')

# 创建线程
t = threading.Thread(target=worker)

# 启动线程
t.start()

# 等待线程结束
t.join()

print('Main thread finished')

在上面的代码中,我们首先定义了一个名为worker()的函数,该函数将在新线程中执行。然后,我们使用threading.Thread()函数创建一个新线程,并将worker()函数作为线程的目标函数。接着,我们使用t.start()方法启动线程。在主线程中,我们使用t.join()方法等待新线程执行完成。最后,我们输出一条消息表示主线程已经结束。

需要注意的是,Python的threading模块虽然可以实现多线程编程,但由于GIL(全局解释器锁)的存在,多线程并不能真正地实现并行执行,而只能实现并发执行。如果需要实现真正的并行执行,可以考虑使用multiprocessing模块或者使用其他语言编写多线程程序。

全局解释器锁

全局解释器锁(Global Interpreter Lock,简称 GIL)是 Python 解释器中的一个机制,它的作用是保证同一时刻只有一个线程在执行 Python 代码。这个机制的存在是为了保证 Python 的内存管理的安全性,因为 Python 的内存管理机制是基于引用计数的,多线程同时操作同一个对象的引用计数可能会导致内存错误。但是 GIL 也限制了多线程的并行执行,因为在同一时刻只有一个线程在执行 Python 代码,其他线程只能等待 GIL 的释放才能执行。因此,在需要大量 CPU 密集型计算的情况下,使用多线程并不能提高 Python 程序的执行效率。

multiprocessing

multiprocessing 是 Python 内置的一个用于支持多进程编程的模块,它提供了一个 Process 类,可以用来创建和管理进程。与多线程不同的是,每个进程都有自己独立的 Python 解释器和 GIL,因此多个进程可以并行执行 Python 代码,从而实现更好的 CPU 利用率。

使用 multiprocessing 模块创建进程的方式与使用 threading 模块创建线程的方式类似,只需要创建一个 Process 对象,并调用其 start() 方法来启动进程。同时,multiprocessing 还提供了一些用于进程间通信和同步的工具,如 QueuePipeValueArray 等,可以方便地在多个进程之间传递数据和共享内存。

import multiprocessing

def worker1(queue):
    for i in range(10):
        queue.put(f"Message from worker1: {i}")
        
def worker2(queue):
    for i in range(10):
        msg = queue.get()
        print(f"Received: {msg}")

if __name__ == '__main__':
    queue = multiprocessing.Queue()
    p1 = multiprocessing.Process(target=worker1, args=(queue,))
    p2 = multiprocessing.Process(target=worker2, args=(queue,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()

在这个例子中,我们首先定义了两个函数 worker1 和 worker2,分别用于向队列中发送消息和从队列中接收消息。然后在 main 函数中创建了一个 Queue 对象,并将其作为参数传递给两个子进程。接着,我们创建了两个 Process 对象 p1 和 p2,并分别将 worker1 和 worker2 函数作为其目标函数,并传递相应的参数。最后,我们启动了两个子进程,等待它们执行完毕后再退出。在这个例子中,worker1 函数会向队列中发送 10 条消息,而 worker2 函数会从队列中接收这些消息并打印出来。通过这种方式,我们实现了两个子进程之间的简单通信。

协程

除了线程和进程,还有协程(Coroutine)这个概念。协程是一种用户态的轻量级线程,可以在同一个线程中实现多个协程的切换,从而达到并发执行的效果。相比于线程和进程,协程的开销更小,切换更快,但是也有一些局限性,比如无法利用多核 CPU 等。在 Python 中,可以使用 asyncio 模块来实现协程。

协程是一种用户态的轻量级线程,可以在同一个线程中实现多个协程的切换,从而达到并发执行的效果。协程相比于线程和进程,具有以下优点:

更小的开销:协程的创建和切换开销都比线程和进程要小,因为协程是在同一个线程中运行的,不需要进行上下文切换和内存分配等操作。

更快的切换:协程的切换是由程序自身控制的,可以在适当的时候进行切换,因此切换的速度更快。

更高的并发性:协程的并发性可以达到线程和进程的水平,因为可以在同一个线程中运行多个协程,从而实现并发执行。

在 Python 中,可以使用 asyncio 模块来实现协程。asyncio 提供了一些基础的协程函数和协程对象,可以通过 async/await 语法来实现协程的编写。

asyncio

import asyncio

async def hello():
    print('Hello')
    await asyncio.sleep(1)
    print('World')

async def main():
    tasks = [hello(), hello()]
    await asyncio.gather(*tasks)

if __name__ == '__main__':
    asyncio.run(main())

这个例子中,hello() 函数是一个协程函数,通过 async/await 语法来定义。在 hello() 函数中,先输出 Hello,然后通过 asyncio.sleep(1) 来模拟一个耗时的操作,最后输出 World。

在 main() 函数中,我们创建了两个 hello() 协程对象,并将它们作为任务添加到 tasks 列表中。然后使用 asyncio.gather() 函数来并发执行这些任务。

最后,在 if name == ‘main’ 中,我们使用 asyncio.run() 函数来运行 main() 协程,从而实现了协程的并发执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值