【Python】教你彻底了解Python中的并发编程

news2024/12/23 23:19:26

​​​​在这里插入图片描述

文章目录

    • 一、并发编程的基本概念
      • 1. 线程(Thread)
      • 2. 进程(Process)
      • 3. 协程(Coroutine)
    • 二、Python中的线程与进程
      • 1. 线程
        • 1.1 创建和启动线程
        • 1.2 线程同步
      • 2. 多进程
        • 2.1 创建和启动进程
        • 2.2 进程间通信
    • 三、异步编程
      • 1. 协程
        • 1.1 定义和调用协程
      • 2. 异步任务
    • 四、并发编程的实际应用示例
      • 1. 多线程Web爬虫
      • 2. 多进程图像处理
    • 五、并发编程的注意事项
      • 1. 线程安全
      • 2. 死锁
      • 3. 资源消耗
      • 4. 异常处理
    • 结论

随着计算机处理能力的不断提升和多核处理器的普及,并发编程变得越来越重要。并发编程可以使程序同时执行多个任务,从而提高程序的性能和响应速度。在Python中,有多种方式可以实现并发编程,包括线程、进程和异步编程。在这篇文章中,我们将深入探讨Python中的并发编程,涵盖其基本概念、线程与进程、多线程编程、多进程编程、异步编程以及并发编程的实际应用示例。

一、并发编程的基本概念

并发编程是指同时执行多个任务的编程技术。并发编程的目标是提高程序的执行效率和响应速度。在并发编程中,有几个重要的概念需要理解:

1. 线程(Thread)

线程是程序执行的最小单位。一个进程可以包含多个线程,每个线程可以执行不同的任务。线程之间可以共享内存,因此线程之间的通信比较容易,但需要注意线程安全问题。

2. 进程(Process)

进程是程序执行的一个实例。每个进程有自己独立的内存空间,相互之间不会影响。多进程编程可以有效利用多核处理器,但进程之间的通信相对复杂。

3. 协程(Coroutine)

协程是一种比线程更轻量级的并发实现方式。协程在执行过程中可以暂停和恢复,从而实现非阻塞的并发执行。Python中的异步编程通常使用协程来实现。

二、Python中的线程与进程

Python中提供了多种实现并发编程的方式,包括线程、多进程和异步编程。我们将分别介绍这些方法,并讨论它们的优缺点。

1. 线程

Python中的threading模块提供了创建和管理线程的功能。通过threading.Thread类,我们可以创建和启动线程。

1.1 创建和启动线程

以下示例展示了如何创建和启动线程:

import threading

def print_numbers():
    for i in range(1, 6):
        print(i)

# 创建线程
thread = threading.Thread(target=print_numbers)

# 启动线程
thread.start()

# 等待线程结束
thread.join()
print("Thread execution completed.")

在上面的例子中,我们创建了一个线程来执行print_numbers函数,并启动了线程。join方法用于等待线程执行完成。

1.2 线程同步

在多线程编程中,多个线程可能会同时访问共享资源,从而导致数据不一致的问题。为了避免这种情况,我们可以使用线程同步机制,如锁(Lock)。

以下示例展示了如何使用锁来同步线程:

import threading

counter = 0
lock = threading.Lock()

def increment_counter():
    global counter
    for _ in range(1000000):
        with lock:
            counter += 1

# 创建和启动线程
threads = []
for _ in range(5):
    thread = threading.Thread(target=increment_counter)
    threads.append(thread)
    thread.start()

# 等待所有线程结束
for thread in threads:
    thread.join()

print(f"Final counter value: {counter}")

在上面的例子中,我们使用锁来确保每次只有一个线程可以访问和修改counter变量,从而避免数据不一致的问题。

2. 多进程

Python中的multiprocessing模块提供了创建和管理进程的功能。多进程编程可以有效利用多核处理器,提高程序的执行效率。

2.1 创建和启动进程

以下示例展示了如何创建和启动进程:

import multiprocessing

def print_numbers():
    for i in range(1, 6):
        print(i)

# 创建进程
process = multiprocessing.Process(target=print_numbers)

# 启动进程
process.start()

# 等待进程结束
process.join()
print("Process execution completed.")

在上面的例子中,我们创建了一个进程来执行print_numbers函数,并启动了进程。join方法用于等待进程执行完成。

2.2 进程间通信

进程之间有独立的内存空间,因此进程间通信相对复杂。Python的multiprocessing模块提供了多种进程间通信的机制,如队列(Queue)和管道(Pipe)。

以下示例展示了如何使用队列进行进程间通信:

import multiprocessing

def producer(queue):
    for i in range(5):
        queue.put(i)
        print(f"Produced: {i}")

def consumer(queue):
    while True:
        item = queue.get()
        if item is None:
            break
        print(f"Consumed: {item}")

# 创建队列
queue = multiprocessing.Queue()

# 创建和启动生产者和消费者进程
producer_process = multiprocessing.Process(target=producer, args=(queue,))
consumer_process = multiprocessing.Process(target=consumer, args=(queue,))

producer_process.start()
consumer_process.start()

# 等待生产者进程结束
producer_process.join()

# 发送终止信号给消费者进程
queue.put(None)

# 等待消费者进程结束
consumer_process.join()
print("Producer and Consumer execution completed.")

在上面的例子中,我们使用队列来在生产者和消费者进程之间传递数据。

三、异步编程

异步编程是一种高效的并发编程方式,尤其适用于I/O密集型任务。Python中的asyncio模块提供了异步编程的支持,可以使用协程实现非阻塞的并发执行。

1. 协程

协程是一种可以在执行过程中暂停和恢复的函数。协程使用async def关键字定义,使用await关键字调用。

1.1 定义和调用协程

以下示例展示了如何定义和调用协程:

import asyncio

async def print_numbers():
    for i in range(1, 6):
        print(i)
        await asyncio.sleep(1)

# 获取事件循环
loop = asyncio.get_event_loop()

# 运行协程
loop.run_until_complete(print_numbers())
loop.close()
print("Coroutine execution completed.")

在上面的例子中,我们定义了一个协程print_numbers,并在事件循环中运行它。await asyncio.sleep(1)用于模拟异步操作。

2. 异步任务

在异步编程中,我们可以使用asyncio.create_task创建异步任务,并使用await等待任务完成。

以下示例展示了如何创建和管理异步任务:

import asyncio

async def print_numbers():
    for i in range(1, 6):
        print(i)
        await asyncio.sleep(1)

async def main():
    # 创建异步任务
    task1 = asyncio.create_task(print_numbers())
    task2 = asyncio.create_task(print_numbers())

    # 等待所有任务完成
    await asyncio.gather(task1, task2)

# 获取事件循环并运行主协程
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
print("All tasks completed.")

在上面的例子中,我们创建了两个异步任务,并使用asyncio.gather等待它们全部完成。

四、并发编程的实际应用示例

并发编程在实际应用中有广泛的应用,以下是两个实际应用示例,演示如何使用Python进行并发编程。

1. 多线程Web爬虫

以下示例演示如何使用多线程实现一个简单的Web爬虫:

import threading
import requests
from bs4 import BeautifulSoup

urls = [
    'https://www.example.com/page1',
    'https://www.example.com/page2',
    'https://www.example.com/page3'
]

def fetch_url(url):
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')
    title = soup.title.string
    print(f"Title of {url}: {title}")

# 创建和启动线程
threads = []
for url in urls:
    thread = threading.Thread(target=fetch_url, args=(url,))
    threads.append(thread)
    thread.start()

# 等待所有线程结束
for thread in threads:
    thread.join()

print("All URLs fetched.")

在上面的例子中,我们使用多线程来并发获取多个网页的标题,从而提高爬取效率。

2. 多进程图像处理

以下示例演示如何使用多进程实现并行图像处理:

import multiprocessing
from PIL import Image, ImageFilter

image_paths = [
    'image1.jpg',
    'image2.jpg',
    'image3.jpg'
]

def process_image(image_path):
    image = Image.open(image_path)
    image = image.filter(ImageFilter.GaussianBlur(5))
    output_path = f"processed_{

image_path}"
    image.save(output_path)
    print(f"Processed {image_path} and saved as {output_path}")

# 创建和启动进程
processes = []
for image_path in image_paths:
    process = multiprocessing.Process(target=process_image, args=(image_path,))
    processes.append(process)
    process.start()

# 等待所有进程结束
for process in processes:
    process.join()

print("All images processed.")

在上面的例子中,我们使用多进程来并行处理多个图像,从而提高图像处理的效率。

五、并发编程的注意事项

并发编程可以显著提高程序的性能,但同时也带来了一些挑战和问题。以下是一些并发编程的注意事项:

1. 线程安全

在多线程编程中,多个线程可能会同时访问共享资源,从而导致数据不一致的问题。为了避免这种情况,我们需要使用线程同步机制,如锁(Lock)、信号量(Semaphore)等。

2. 死锁

死锁是指两个或多个线程互相等待对方释放资源,从而导致程序无法继续执行的情况。为了避免死锁,我们需要小心设计线程同步机制,避免循环等待的情况。

3. 资源消耗

线程和进程的创建和管理会消耗系统资源。在实际应用中,我们需要合理控制线程和进程的数量,避免资源浪费。

4. 异常处理

在并发编程中,异常处理尤为重要。我们需要捕获和处理并发任务中的异常,确保程序的稳定性和可靠性。

结论

并发编程是现代编程中的一个重要技术,可以显著提高程序的性能和响应速度。在Python中,有多种方式可以实现并发编程,包括线程、多进程和异步编程。通过理解和掌握这些技术,我们可以编写出更加高效和可靠的程序。在本文中,我们详细讨论了并发编程的基本概念、Python中的线程与进程、多线程编程、多进程编程、异步编程以及并发编程的实际应用示例。希望这篇文章能帮助你更好地理解和应用Python中的并发编程技术,从而在实际项目中获得更多的性能提升和优化效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1794463.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

p2p文件传输小工具

使用webRTC的相关技术栈可以很轻松的开发一个p2p文件传输工具,这里主要讲下使用datachannel开发的一个文件传输工具client程序的使用 客户端A:需要可以访问公网,运行client的主机 客户端B:可以访问公网,可以和客户端…

关于三极管的理解

三极管工作时出现三个状态:截止、放大、饱和 1. 截止状态:三极管处于关断状态,Vce约等于电源电压 2. 放大状态:三极管处于电流放大状态,0V 3. 饱和状态:三极管处于完全导通状态,Vce≈0V 放大电…

卡尔曼滤波(Kalman Filtering)详细解读

🧑‍🎓 个人主页:《爱蹦跶的大A阿》 🔥当前正在更新专栏:《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ ​ ✨ 前言 卡尔曼滤波(Kalman Filtering)是一种用于估计…

天润酸奶爆改饭盒?为什么听劝营销“硬控”消费者如此有效

不知道大家会不会经常逛超市?有没有发现酸奶货架上有一道异于其它品牌的包装,它就是新疆天润酸奶,酷似饭盒的外包装对于当代倡导实用主义的年轻人来讲,这一发现无疑是直接“创进心巴”,不少网友表示它直接解决了带饭人…

新零售智能售卖教学实训沙盘内容介绍

新零售智能售卖教学实训沙盘是服务数据分析的教学工具。通过该沙盘,能够让学生了解数据分析在新零售行业智能售卖业务场景的应用流程。使用新零售智能售卖教学实训沙盘进行教学,一方面能够让老师的教学内容更加贴近实际应用,将教学场景具象化…

音视频开发13 FFmpeg 音频 相关格式分析 -- AAC ADTS格式分析

这一节,我们学习常用的音频的格式 AAC,重点是掌握 AAC的传输格式 ADTS 头部的信息,目的是 : 当音频数据有问题的时候,如果是AAC的编码,在分析 头部信息的时候能够根据头部信息 判断问题是否出现在 头部。 A…

搜狗输入法的软键盘怎么关闭

我的搜狗输入法软件盘和typora中ctrlshiftk冲突了,关闭软键盘

doris FE 在Windows环境下编译调试开发环境

前言: doris fe 在win下调试运行,和正常java项目有一些差异,主要是有与be(c)通信代码的生成 在win环境下不能直接生成,因此需要现在linux下生成之后,再拷贝到本地来,然后进行编译&a…

锻炼 精读笔记 01

元数据 [!abstract] 锻炼 书名: 锻炼作者: 丹尼尔利伯曼简介: 我们是为休息而生,还是为跑而生? 跑步会毁了你的膝盖吗? 哪种运动项目蕞适合我? 懒惰是不正常的行为吗? 每晚都需要睡够 8 个小时…

机器学习是什么?它又如何在网络安全中使用?

介绍 本文概述了基础机器学习概念,并解释了机器学习在网络安全行业中日益增长的应用,以及主要优势、主要用例、常见误解和 CrowdStrike 的机器学习方法。 什么是机器学习? 机器学习 (ML) 是人工智能 (AI…

RockPI 4A单板Linux 4.4内核下的RK3399 GPIO功能解析

RockPI 4A单板Linux 4.4内核下的RK3399 GPIO功能解析 摘要:本文将基于RockPI 4A单板,介绍Linux 4.4内核下RK3399 GPIO(通用输入输出)功能的使用方法。通过详细的代码解析和示例,帮助读者理解如何在Linux内核中使用GPI…

MySQL条件查询

018条件查询之或者or or表示或者,还有另一种写法:|| 案例:找出工作岗位是MANAGER和SALESMAN的员工姓名、工作岗位 注意字符串一定要带单引号 select ename, job from emp where jobmanager or jobsalesman;任务:查询20和30部门的…

信息系统项目管理师0145:敏捷与适应方法(9项目范围管理—9.2项目范围管理过程—9.2.3敏捷与适应方法)

点击查看专栏目录 文章目录 9.2.3 敏捷与适应方法9.2.3 敏捷与适应方法 对于需求不断变化、风险大或不确定性高的项目,在项目开始时通常无法明确项目的范围,而需要在项目期间逐渐明确。敏捷或适应型方法特意在项目早期缩短定义和协商范围的时间,为后续细化范围、明确范围争取…

海思Hi3519DV500方案1200万无人机吊舱套板

海思Hi3519DV500方案1200万无人机吊舱套板 Hi3519DV500 是一颗面向行业市场推出的超高清智能网络摄像头SoC。该芯片最高 支持四路sensor 输入,支持最高4K30fps 的ISP 图像处理能力,支持2F WDR、 多级降噪、六轴防抖、全景拼接、多光谱融合等多种传统图像…

一种用于异质结高电子迁移率晶体管(HEMTs)的紧凑型漏电流模型,其中包括双子带的二维电子气(2DEG)密度解

来源:A compact drain current model for heterostructure HEMTs including 2DEG density solution with two subbands(Solid-State Electronics 16年) 摘要 本文提出了一种针对异质结高电子迁移率晶体管(HEMTs)的二维电子气(2DEG)电荷密度…

数组array 和 array的区别

问题 对于数组 array和&array有什么区别呢? 先说答案 array: 指向数组第一个数地址的指针 &array: 指向整个数组地址的指针 所以直接打印的话, 地址是一样的. 但是如果1的话, 那么array是增加sizeof(int)大小, &array是增加sizeof(int) * array.size() 测试 #i…

[AVL数四种旋转详细图解]

文章目录 一.右单旋二. 左单旋三. 右左双旋四. 左右双旋 一.右单旋 新节点插入较高左子树的左侧—左左:右单旋 由于在较高左子树的左侧插入一个节点后,左边插入导致30的平衡因子更新为-1,而60平衡因子更新为-2,此时不平衡&…

Elastic Search 8.14:更快且更具成本效益的向量搜索,使用 retrievers 和重新排序提升相关性,RAG 和开发工具

作者:来自 Elastic Yaru Lin, Ranjana Devaji 我们致力于突破搜索开发的界限,并专注于为搜索构建者提供强大的工具。通过我们的最新更新,Elastic 对于处理以向量表示的大量数据的客户来说变得更加强大。这些增强功能保证了更快的速度、降低的…

【精选案例】Sellfy | 电子商务平台怎么利用客户裂变系统实现用户增长?

Sellfy是一种基于云的电子商务解决方案,特别为数字内容创作者所设计。 一、主要目标用户: Sellfy主要针对的是包括作家、插画家、设计师、音乐家和电影制作人在内的数字内容创作者,他们可以在Sellfy上在线销售自己的产品。 二、平台特点&a…

KIBANA的安装教程(超详细)

前言 Kibana 是一个开源的基于浏览器的可视化工具,主要用于分析和展示存储在 Elasticsearch 索引中的数据。它允许用户通过各种图表、地图和其他可视化形式来探索和理解大量数据。Kibana 与 Elasticsearch 和 Logstash 紧密集成,共同构成了所谓的 ELK 堆…