CPU密集的高效访问和数据安全

2024-03-24 20:20

本文主要是介绍CPU密集的高效访问和数据安全,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

import asyncio
import concurrent.futures
import random

# 全局变量,用于存储计算结果的列表
list1 = []
list2 = []
lock = asyncio.Lock()  # 异步锁

# CPU计算密集型任务
async def cpu_intensive_task():
    global list1, list2

    # 获取异步锁
    async with lock:
        # 进行CPU计算密集型任务,这里简单地生成随机数并添加到列表中
        random_number = random.randint(1, 100)
        list1.append(random_number)
        list2.append(random_number * 2)

# 读取协程函数
async def reader_coroutine():
    global list1, list2

    while True:
        # 获取异步锁
        async with lock:
            # 读取列表1和列表2的值
            print(f"List 1: {list1}")
            print(f"List 2: {list2}")
        await asyncio.sleep(1)  # 每隔1秒读取一次

# 创建事件循环对象
loop = asyncio.get_event_loop()

# 创建多个读取协程并添加到事件循环中
readers = [reader_coroutine() for _ in range(5)]  # 创建5个读取协程

# 同时执行CPU计算密集型任务和读取协程
tasks = [cpu_intensive_task(), *readers]
loop.run_until_complete(asyncio.gather(*tasks))

# 关闭事件循环
loop.close()

上面的cpu_intensive_task 函数是CPU密集型,里面没有await和IO操作,就只有这个函数里修改两个全局变量list1和list2,其他协程函数都是读取。根据我们上面的总结,也就是我们可以不用加锁,也不会导致其他协程任务读到的数据两个全局变量list1和list2的数据不一致问题吗?

是的,根据我们之前的讨论和总结,如果 cpu_intensive_task 函数是一个纯粹的 CPU 密集型任务,没有涉及到 IO 操作或者 await 表达式,而且只是修改两个全局变量 list1list2,那么在这种情况下,可以不用加锁。

因为在 Python 中的 GIL(全局解释器锁)机制下,对于 CPU 密集型任务,即使有多个线程或者协程在执行,它们也无法同时访问同一个 CPU 核心,因此不会出现多个协程同时修改全局变量导致数据不一致的问题。

所以,在你的情况下,cpu_intensive_task 函数只是修改两个全局变量 list1list2,而其他协程函数只是读取这两个全局变量的值,因此不需要加锁也不会导致数据不一致的问题

那如果cpu_intensive_task 这个异步函数里有一部分存在读取文件,但是这个函数里面都没有使用await关键字或者有await关键字但await不会出现在修改两个全局变量list1和list2的中间位置,还是可以不用加锁吗?

在你描述的情况下,即使 cpu_intensive_task 函数中包含了一部分读取文件的操作,但没有使用 await 关键字或者 await 关键字不会出现在修改全局变量 list1list2 的中间位置,依然可以不用加锁。

异步编程中,如果一个协程内部有 IO 操作,但是这些 IO 操作不是通过 await 关键字等待的话,不会触发协程的挂起,也不会引起事件循环的切换。因此,只有涉及到 await 表达式才会触发挂起和事件循环的切换。

所以,在你的情况下,即使 cpu_intensive_task 函数中包含了一部分读取文件的操作,只要这些 IO 操作没有使用 await 等待,并且 await 关键字不会出现在修改全局变量 list1list2 的中间位置,依然可以不用加锁。

上面的cpu_intensive_task 这个异步函数里面await关键字 如果等待的是一个计算密集型任务,CPU在执行到这个await时不会让渡出CPU资源,只会阻塞等待任务的执行然后继续执行下面的代码吗?

对于异步函数中使用 await 关键字等待的是一个计算密集型任务,情况会有些不同。Python 中的异步机制实际上是基于事件循环的协作式调度,当遇到 await 表达式时,如果等待的是一个计算密集型任务(例如在同一个线程内的一些 CPU 密集型操作),那么 await 表达式会阻塞当前协程并暂时放弃 CPU 控制权,而不是等待任务的执行然后继续执行下面的代码。

这是因为在 Python 中,GIL(全局解释器锁)的存在导致了对于 CPU 密集型任务的并行执行无法真正实现。当一个协程遇到 await 表达式等待一个 CPU 密集型任务时,事件循环实际上会挂起这个协程,然后切换到其他就绪状态的协程执行。这样可以在遇到长时间的 CPU 计算时,避免整个事件循环被阻塞,提高了程序的并发性能。

所以,总的来说,异步函数中 await 关键字等待的是一个计算密集型任务时,不会让出 CPU 资源,而是暂时放弃 CPU 控制权,让事件循环调度其他协程执行,然后等待任务完成后再继续执行下面的代码。

也就是CPU遇到await关键字不管后面是否是CPU密集型任务还是IO任务都会暂时放弃当前任务的控制权,转而执行其他待续任务,而当执行awai后面的CPU密集任务时,CPU并不会任意切换到其他任务中?

是的,你的理解基本上是正确的。

在 Python 中,遇到 await 关键字时,不管后面是 CPU 密集型任务还是 IO 密集型任务,当前协程都会暂时放弃 CPU 控制权,转而执行其他待续任务,让事件循环调度其他协程执行。这是异步编程中的协作式调度机制,目的是避免阻塞整个事件循环。

当执行到 await 后面的 CPU 密集型任务时,因为 Python 中的 GIL(全局解释器锁)的存在,任务并不会真正实现并行执行,而是仍然在单个 CPU 核心上执行。但是由于事件循环的调度机制,当前协程会暂时放弃 CPU 控制权,让事件循环调度其他协程执行。这样可以避免一个长时间的 CPU 密集型任务阻塞整个事件循环,提高了程序的并发性能。

You

你的意思是当执行到 await 后面的 CPU 密集型任务里面时,CPU随时都可能让渡出计算资源转而执行其他任务里的代码?

不完全正确。在 Python 中,对于 CPU 密集型任务,当执行到 await 后面的 CPU 密集型任务时,CPU 不会随时让渡出计算资源转而执行其他任务里的代码。在单个线程内,CPU 密集型任务的执行会一直占用 CPU 资源,直到任务执行完成才会继续执行其他任务。

具体来说,当一个协程遇到 await 表达式等待一个 CPU 密集型任务时,该协程会暂时挂起,让出 CPU 控制权,但并不会让渡出计算资源,因为 Python 中的 GIL(全局解释器锁)的存在导致在单个线程内只能有一个线程执行 Python 字节码。因此,即使事件循环切换到其他协程,CPU 仍然会继续执行当前 CPU 密集型任务,直到任务执行完成或者遇到 IO 操作或者 await 关键字等待其他协程。

总之,CPU 密集型任务的执行不会随时让渡出计算资源转而执行其他任务里的代码,而是会一直执行直到完成或者遇到挂起条件。异步编程中的优势主要体现在 IO 密集型任务的异步执行上,对于 CPU 密集型任务,异步编程并不能提升性能。

这篇关于CPU密集的高效访问和数据安全的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/842675

相关文章

使用Python构建一个高效的日志处理系统

《使用Python构建一个高效的日志处理系统》这篇文章主要为大家详细讲解了如何使用Python开发一个专业的日志分析工具,能够自动化处理、分析和可视化各类日志文件,大幅提升运维效率,需要的可以了解下... 目录环境准备工具功能概述完整代码实现代码深度解析1. 类设计与初始化2. 日志解析核心逻辑3. 文件处

Java docx4j高效处理Word文档的实战指南

《Javadocx4j高效处理Word文档的实战指南》对于需要在Java应用程序中生成、修改或处理Word文档的开发者来说,docx4j是一个强大而专业的选择,下面我们就来看看docx4j的具体使用... 目录引言一、环境准备与基础配置1.1 Maven依赖配置1.2 初始化测试类二、增强版文档操作示例2.

Linux进程CPU绑定优化与实践过程

《Linux进程CPU绑定优化与实践过程》Linux支持进程绑定至特定CPU核心,通过sched_setaffinity系统调用和taskset工具实现,优化缓存效率与上下文切换,提升多核计算性能,适... 目录1. 多核处理器及并行计算概念1.1 多核处理器架构概述1.2 并行计算的含义及重要性1.3 并

Linux下进程的CPU配置与线程绑定过程

《Linux下进程的CPU配置与线程绑定过程》本文介绍Linux系统中基于进程和线程的CPU配置方法,通过taskset命令和pthread库调整亲和力,将进程/线程绑定到特定CPU核心以优化资源分配... 目录1 基于进程的CPU配置1.1 对CPU亲和力的配置1.2 绑定进程到指定CPU核上运行2 基于

MySQL中的InnoDB单表访问过程

《MySQL中的InnoDB单表访问过程》:本文主要介绍MySQL中的InnoDB单表访问过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、访问类型【1】const【2】ref【3】ref_or_null【4】range【5】index【6】

在Golang中实现定时任务的几种高效方法

《在Golang中实现定时任务的几种高效方法》本文将详细介绍在Golang中实现定时任务的几种高效方法,包括time包中的Ticker和Timer、第三方库cron的使用,以及基于channel和go... 目录背景介绍目的和范围预期读者文档结构概述术语表核心概念与联系故事引入核心概念解释核心概念之间的关系

前端如何通过nginx访问本地端口

《前端如何通过nginx访问本地端口》:本文主要介绍前端如何通过nginx访问本地端口的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、nginx安装1、下载(1)下载地址(2)系统选择(3)版本选择2、安装部署(1)解压(2)配置文件修改(3)启动(4)

SpringMVC高效获取JavaBean对象指南

《SpringMVC高效获取JavaBean对象指南》SpringMVC通过数据绑定自动将请求参数映射到JavaBean,支持表单、URL及JSON数据,需用@ModelAttribute、@Requ... 目录Spring MVC 获取 JavaBean 对象指南核心机制:数据绑定实现步骤1. 定义 Ja

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

Python基于微信OCR引擎实现高效图片文字识别

《Python基于微信OCR引擎实现高效图片文字识别》这篇文章主要为大家详细介绍了一款基于微信OCR引擎的图片文字识别桌面应用开发全过程,可以实现从图片拖拽识别到文字提取,感兴趣的小伙伴可以跟随小编一... 目录一、项目概述1.1 开发背景1.2 技术选型1.3 核心优势二、功能详解2.1 核心功能模块2.