Python多任务处理---多线程

引入   

        生活中,我们在电脑上打开了一个word,    这个word对操作系统来说就是一个进程。我们在进行word操作的时候,比如在你打字的时候,该word同时可以进行文字检查。发现了没,在同一个进程中,我们也可以进行同时操作。这就带来了线程的概念。在一个进程中,要同时干多件事,就需要同时运行多个“子任务”,我们把这些子任务可以叫做线程。​​​​​​​

线程出现的背景及意义 

        线程的出现和意义可以从几个方面来理解,主要包括计算机历史背景的发展、效率和资源管理的需要、以及对并发编程模型的追求。

计算机历史背景

        早期的计算机系统大多是单任务的,即计算机在任何时刻只能执行一个任务。随着计算机技术的发展,人们对计算机的处理能力和效率提出了更高的要求,这促使操作系统向多任务系统发展。在多任务操作系统中,多个任务(进程)可以共享CPU时间,使得计算机资源得到更有效的利用。

效率和资源管理

        进程作为操作系统资源分配和调度的基本单位,拥有独立的地址空间和系统资源。这种设计在隔离性和安全性方面有显著优势,但进程的创建、销毁和切换代价较高,资源开销大。为了减少这种开销,提高系统的并发性和响应速度,线程被引入作为轻量级的进程。

线程(有时被称为轻量级进程)共享同一进程的地址空间和资源,但拥有独立的执行路径和栈空间。这种设计使得线程的创建、销毁和切换的开销远小于进程,从而大大提高了系统的效率。

对并发编程模型的追求

        随着多核处理器的出现和发展,利用并发和并行编程模型来充分利用多核处理器的计算能力变得尤为重要。线程作为实现并发执行的基本单位,使得开发者可以更容易地编写出能够充分利用多核处理器性能的程序。

        线程不仅可以在多核处理器上并行执行,提高程序的执行效率,而且在单核处理器上也能通过时间分片技术实现并发执行,提高响应速度和资源利用率。此外,线程还支持更细粒度的任务划分和更灵活的控制,有助于实现复杂的并发编程模型,如响应式编程、事件驱动编程等。

总结

        线程的出现主要是为了提高程序的执行效率和响应速度,减少操作系统在任务管理上的开销,并更好地利用多核处理器的计算能力。线程使得并发和并行编程成为可能,为开发高性能、高响应速度的应用程序提供了基础。

关键概念和术语

        Python中的多线程编程涉及到一系列的概念和术语。下面列出了一些关键概念,以及如何使用threading模块进行多线程编程的基本示例。  

  • 线程(Thread): 是程序执行中一个单一的顺序控制流程,线程是操作系统处理器能够进行运算调度的最小单位。它被包含在进程之中,一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间),是进程中的实际运作单位。在Python中,threading模块允许我们创建和管理线程。

  • 主线程(Main Thread):Python程序启动时,默认会创建一个线程,称为主线程。程序中的所有代码默认都在主线程中执行,除非显式地创建新的线程。

  • 子线程(Child Thread):通过程序创建的新线程称为子线程。程序可以同时运行多个子线程,以执行并行操作。

  • 线程同步(Thread Synchronization):当多个线程需要共享数据或资源时,需要确保这些共享资源不会同时被多个线程修改,以避免数据不一致或状态混乱的问题。常用的线程同步机制包括锁(Locks)、事件(Events)、条件(Conditions)等。

  • 死锁(Deadlock):当两个或多个线程在等待对方释放资源,而这些资源又被对方占用时,会导致这些线程无限等待,发生死锁。

 多进程和多线程的区别

  1. 多线程可以共享全局变量,多进程不能。
  2. 多线程中,所有子线程的进程号相同;多进程中,不同的子进程进程号不同。
  3. 线程共享内存空间;进程的内存是独立的
  4. 同一个进程之间的线程可以直接通信,而两个进程之间的通信需要代理
  5. 一个线程可控制和操作同一进程里的其它线程,进程只能操作子进程
  6. 在多进程中,同一个变量,各自有一份拷贝存在于每一个进程中,互不影响;而多线程中,所有的变量都有线程共享。

   参考:https://www.cnblogs.com/qianqiannian/p/7010909.html

常用代码示例 

创建和启动线程
import threading

def thread_function(name):
    print(f"Thread {name} is running")

if __name__ == "__main__":
    # 创建线程
    my_thread = threading.Thread(target=thread_function, args=("MyThread",))
    # 启动线程
    my_thread.start()
    # 等待线程完成
    my_thread.join()
    print("Main    : all done")
使用锁进行线程同步
import threading

# 创建一个锁
lock = threading.Lock()

def thread_function(name):
    lock.acquire()  # 获取锁
    try:
        print(f"Thread {name} is running")
    finally:
        lock.release()  # 释放锁

if __name__ == "__main__":
    for i in range(5):
        my_thread = threading.Thread(target=thread_function, args=(i,))
        my_thread.start()
        my_thread.join()  # 注意:在实际应用中,通常不会在这里立即调用join()
使用with语句简化锁的操作
import threading

# 创建一个锁
lock = threading.Lock()

def thread_function(name):
    with lock:
        print(f"Thread {name} is running")

if __name__ == "__main__":
    for i in range(5):
        my_thread = threading.Thread(target=thread_function, args=(i,))
        my_thread.start()
        my_thread.join()

注意事项

  • 全局解释器锁(GIL):由于Python的全局解释器锁(GIL),在CPython解释器中,即使在多核处理器上,同一时刻只能有一个线程执行Python字节码。这意味着,对于CPU密集型任务,使用多线程并不能达到理想的并行效果。在这种情况下,可以考虑使用多进程(multiprocessing模块)来实现真正的并行计算。
  • I/O密集型任务:对于I/O密集型任务(例如文件读写、网络请求等),多线程可以有效提高程序性能,因为线程可以在等待I/O操作完成时让出CPU,执行其他任务。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Pytorch学习笔记(二)】张量的创建(补充)

一、知识回顾 我们在博客《张量的创建与访问》中已经讨论了一些张量的创建方法如torch.CharTensor()、torch.FloatTensor()以及torch.zeros()等张量创建方法,但由于其仅仅介绍了cpu版本torch下张量的创建方法和只有具体数据类型张量,本节内容旨在补充gp…

论文速览 | IEEE TCI, 2022 | 单光子级非视距成像:估计强度与优化重建

注1:本文系"计算成像最新论文速览"系列之一,致力于简洁清晰地介绍、解读非视距成像领域最新的顶会/顶刊论文(包括但不限于 Nature/Science及其子刊; CVPR, ICCV, ECCV, SIGGRAPH, TPAMI; Light‑Science & Applications, Optica 等)。 本次介绍的论文是:<2…

【Git】命令行使用体验大大优化的方法

Git的优化使用 相信很多人&#xff0c;在使用git作为版本管理工具时都会感受到它的方便&#xff0c;但是也会有一些问题困扰着我们&#xff0c;让我们觉得使用体验不是很好。我在使用git的过程中就发现了几个问题&#xff1a;写commit费时、怎么做多人开发的代码审查等等。今天…

代码随想录算法训练营第二十五天| 216.组合总和III,17.电话号码的字母组合

题目与题解 216.组合总和III 题目链接&#xff1a;216.组合总和III 代码随想录题解&#xff1a;216.组合总和III 视频讲解&#xff1a;和组合问题有啥区别&#xff1f;回溯算法如何剪枝&#xff1f;| LeetCode&#xff1a;216.组合总和III_哔哩哔哩_bilibili 解题思路&#xf…

Linux之用户账号、用户组和与账号有关的系统文件

目录 一、基本介绍 1.用户和用户组 2.UID和GID 二、 账户管理 1.查看用户的UID和GID 2.添加账户 3.删除账号 4.修改账号 5.账户口令 三、分组管理 1.新增用户组 2.删除用户组 3.修改用户组 4.用户组切换 四、与账号有关的系统文件 1./etc/passwd 2./etc/shado…

组蛋白脱乙酰酶介导的胃癌肿瘤微环境特征及协同免疫治疗(多组学文献学习)

目录 ①HDAC转录组多数据NMF一次聚类 ②ACRG队列中HDAC单独NMF聚类 ③HDS评分在胃癌中的临床特征和基因组特征 ④高 HDS 可能提示胃癌的“热”肿瘤状态 ⑤HDS是胃癌免疫治疗效果的有力预测指标 ⑥单细胞转录组测序揭示了高HDS和低HDS患者的TME ⑦内皮细胞和成纤维细胞可…

Prometheus+grafana环境搭建mysql(docker+二进制两种方式安装)(三)

由于所有组件写一篇幅过长&#xff0c;所以每个组件分一篇方便查看&#xff0c;前两篇 Prometheusgrafana环境搭建方法及流程两种方式(docker和源码包)(一)-CSDN博客 Prometheusgrafana环境搭建rabbitmq(docker二进制两种方式安装)(二)-CSDN博客 1.监控mysql 1.1官方地址:…

文本评估指标 BLEU,METEOR,ROUGE

文本评估指标 这里注意库包的版本&#xff0c;亲测这个很包敏感&#xff0c;所以一定要调好库版本 nltk 3.6.3 如果这个包的版本不对会报错&#xff0c;很难理解的那种 rouge1.0.1 定义函数 import jieba from rouge import Rouge from nltk.translate.meteor_score import …

CrossOver玩游戏会损害电脑吗 CrossOver玩游戏会卡吗 Mac玩游戏 crossover24免费激活

CrossOver是一款可以在macOS上运行Windows应用程序的软件&#xff0c;它利用了Wine技术&#xff0c;无需安装虚拟机或双系统&#xff0c;可以直接在苹果系统下运行Windows游戏。那么&#xff0c;使用CrossOver玩游戏会损害电脑吗&#xff1f;CrossOver玩游戏会卡吗&#xff1f;…

java中:print与println的区别

目录 区别 区别 print是直接打印输出 println是输出后自动回车到下一行 例如 public class test {public static void main(String[] args){System.out.println("换行");System.out.print("不换行");System.out.println();}}——————————————…

Scala第十五章节(递归的相关概述、Scala阶乘案例、Scala斐波那契数列案例、Scala打印目录文件案例)

章节目标 了解递归的相关概述掌握阶乘案例掌握斐波那契数列案例掌握打印目录文件案例 1. 递归 递归指的就是 方法自己调用自己的情况 . 在涉及到复杂操作时, 我们会经常用到它. 在使用递归时, 要注意以下三点: 递归必须有出口, 否则容易造成 死递归 .递归必须要有规律.构造…

跑spark的yarn模式时RM连不上的情况

在linux控制台跑spark on yarn一个测试案例&#xff0c;日志中总显示RM连yarn服务的时候是&#xff1a;0.0.0.0:8032 具体情况如下图&#xff1a; 我问题出现的原因&#xff0c;总结如下&#xff1a; 1.防火墙没关闭&#xff0c;关闭 2.spark-env.sh这个文件的YARN_CONF_DIR…

爱上数据结构:二叉树的基本概念

​ ​ &#x1f525;个人主页&#xff1a;guoguoqiang. &#x1f525;专栏&#xff1a;数据结构 ​ 一、树的基本概念 1.概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因 为它看起…

鸿蒙OS开发案例:【ArkTS类库多线程CPU密集型任务Worker】

使用Worker进行长时间数据分析 通过某地区提供的房价数据训练一个简易的房价预测模型&#xff0c;该模型支持通过输入房屋面积和房间数量去预测该区域的房价&#xff0c;模型需要长时间运行&#xff0c;房价预测需要使用前面的模型运行结果&#xff0c;因此需要使用Worker。 …

【C++】C++入门第二课(函数重载 | 引用 | 内联函数 | auto关键字 | 指针空值nullptr)

目录 前言 函数重载 概念 重载函数的条件 C支持重载函数的原理--名字修饰 引用 概念 特性 常引用&#xff08;const引用&#xff09; 使用场景 传值&#xff0c;传引用效率比较 引用和指针的区别 内联函数 概念 特性 auto关键字&#xff08;C11&#xff09; a…

golang grpc和protobuf的版本降级问题(version4 -> version3)

最后更新于2024年3月28日 10:57:52 简中没查到类似的文章。一点小事闹麻了&#xff0c;搞了一天&#xff0c;特意发出来造福大家。 所谓的版本就是下面这个东西proto.ProtoPackageIsVersion4或者proto.ProtoPackageIsVersion3&#xff1a; 目的 为了适配旧代码&#xff0c…

C语言之位段

1.位段的声明 位段的声明和结构是类似的&#xff0c;有两个不同&#xff1a; 1.位段的成员必须是 int、unsigned int 或signed int 。 2.位段的成员名后边有一个冒号和一个数字。 比如&#xff1a; struct A {int _a:2;int _b:5;int _c:10;int _d:30; }; A 就是一个位段类型…

阿里云服务器安装SSL证书不起作用的解决方案

阿里云服务器安装SSL证书不起作用的解决方案 在阿里云安装SSL证书后&#xff0c;访问无效&#xff0c;各种检查证书安装没有问题。忽然想到阿里云默认连80端口都没开启&#xff0c;443端口应该也没开启。 登录阿里云控制台 - 云服务器 ECS - 网络与安全 - 安全组 - 管理规则 - …

【Redis】Redis 内存管理,Redis事务,bigkey和hotkey

目录 Redis 内存管理 缓存数据设置过期时间&#xff1f; Redis 是如何判断数据是否过期的呢&#xff1f; 过期删除策略 内存淘汰机制 主从模式下对过期键的处理&#xff1f; LRU和LFU的区别 Redis事务 定义和原理 Redis 事务的注意点&#xff1f; 为什么不支持回滚&a…

C++析构函数

当对象的生存期结束时&#xff0c;系统就会自动执行析构函数清除其数据成员所分配的内存空间。 析构函数的定义格式为&#xff1a; &#xff5e;类名();//没有返回值,没有参数 注&#xff1a; (1&#xff09;析构函数名是由“&#xff5e;”加类名组成的。 &#xff08;2&#…