python-线程与进程

news2024/11/26 16:23:41

进程

程序编写完没有运行称之为程序。正在运行的代码(程序)就是进程。在Python3语言中,对多进程支持的是multiprocessing模块subprocess模块。multiprocessing模块为在子进程中运行任务、通讯和共享数据,以及执行各种形式的同步提供支持。

from multiprocessing import Process
#定义子进程代码
def run_proc():
    print('子进程运行中')

if __name__=='__main__':
    print('父进程运行')
    p=Process(target=run_proc)
    print('子进程将要执行')
    p.start()

multiprocessing 是 Python 的标准库模块,用于在 Python 程序中创建多个进程来并发执行任务。Process 是 multiprocessing 模块中的一个类,用于创建和管理单独的进程。每个 Process 对象都表示一个独立的进程,它可以与主进程同时运行,执行不同的任务。

PCB概念:

操作系统描述程序的运行过程,通过一个结构体task_struct{......},统称为PCB(process control block)。是进程管理和控制的最重要的数据结构。每一个进程均有一个PCB,在创建进程时,建立PCB伴随进程运行的全过程,直到进程撤消而撤消。

进程的分类

1)前台进程:
是指用户可以在终端和进程相互交互的进程
2)后台进程
是指没有占用终端的进程,后台进程不需要和用户交互
3)守护进程:
是指在系统启动时启动,并且在系统关闭时结束的进程

进程间的通信

不同进程之间总会需要传播、交换数据。这里进程之间通信必须通过内核,因为进程的用户空间都是独立的,内核空间是每个进程都共享的“公共区域”,所以研究如何“对话”。(虚拟映射的问题)

共享内存的机制,就是拿出一块虚拟地址空间来,映射到相同的物理内存中。

解决用户态与内核态之间的频繁消息拷贝。

进程池

在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,十几个还好,但如果是上百个,上千个目标,手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效

Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程

进程的特点

动态性:进程是程序的一次执行过程,是临时的,有生命期的是动态产生,动态消亡的:
并发性:任何进程都可以同其他进行一起并发执行;
独立性:进程是系统进行资源分配和调度的一个独立单位
结构性:进程由程序,数据和进程控制块三部分组成;

独立性:每个进程拥有自己独立的内存空间、资源和上下文,进程间彼此独立,互不干扰。如果一个进程崩溃,不会影响其他进程的运行。

独立资源分配:进程拥有自己的资源(如内存、文件句柄等),操作系统为每个进程分配独立的内存地址空间和资源,隔离性强,适合需要高可靠性的任务。

进程间通信(IPC):由于进程相互独立,它们不能直接共享内存,进程之间的数据交换需要使用进程间通信机制(如管道、消息队列、共享内存等),这使得通信相对复杂。

并行执行:在多核CPU上,多个进程可以真正实现并行执行,不受像Python GIL(全局解释器锁)等限制,适合CPU密集型任务,能充分利用多核资源。

上下文切换开销大:进程拥有独立的资源,因此进程切换时,操作系统需要保存和恢复更多的上下文信息(如内存空间、CPU寄存器等),上下文切换的开销比线程大。

适合隔离任务:进程之间的内存和资源是完全独立的,因此适合需要任务隔离的场景,例如在某些任务失败时,其他任务不受影响的需求。

启动速度慢:由于进程创建需要分配独立的资源(如内存),相比线程,启动进程的速度较慢,系统开销更大。

适合CPU密集型任务:进程特别适用于需要高计算能力的任务,能充分利用多核并行的计算能力,而不受内存共享和同步机制的限制。

进程的优点

独立内存空间:每个进程都有独立的内存空间,进程之间互不干扰,一个进程的崩溃不会影响其他进程,隔离性强,安全性高。

充分利用多核CPU:进程可以在多核CPU上并行执行,适合CPU密集型任务,能够绕开Python中的GIL(全局解释器锁)限制。

稳定性高:由于进程是独立的,某个进程的错误不会影响其他进程,适合任务隔离和高可靠性的应用。

进程的缺点

创建和销毁开销大:创建、销毁进程需要分配独立的资源和内存,进程切换的开销比线程大。

进程间通信复杂:进程间不能直接共享内存,必须通过进程间通信(如管道、队列、共享内存等),增加了复杂性和延迟。

启动速度慢:由于需要分配独立资源,创建进程比创建线程慢,适合较长时间运行的任务,不适合频繁创建销毁的场景。

举个列子:

计算数字平方并写入文件

import multiprocessing

def write_to_file(filename, number):
    square = number ** 2  # 计算数字的平方
    with open(filename, 'a') as f:  # 以追加模式打开文件
        f.write(f'The square of {number} is {square}\n')

def process_task(filename, number):
    write_to_file(filename, number)

if __name__ == "__main__":
    filename = "output_process.txt"

    # 创建进程池
    processes = []
    for i in range(1, 6):  # 启动5个进程,分别计算1到5的平方
        p = multiprocessing.Process(target=process_task, args=(filename, i))
        processes.append(p)
        p.start()

    # 等待所有进程完成
    for p in processes:
        p.join()

    # 读取并输出文件的内容
    with open(filename, 'r') as f:
        content = f.read()
    print("File content:\n", content)

线程

线程也是实现多任务的一种方式,一个进程中,也经常需要同时做多件事,就需要同时运行多个‘子任务’,这些子任务就是线程一个进程可以拥有多个并行的线程,其中每一个线程,共享当前进程的资源

Python程序中,可以通过“_thread”和threading(推荐使用)这两个模块来处理线程。在Python3中,thread模块已经废弃。可以使用threading模块代替。所以,在Python3中不能再使用thread模块,但是为了兼容Python3以前的程序,在Python3中将thread模块重命名为“_thread”。

threading模块

Python3 通过两个标准库 _thread 和 threading 提供对线程的支持。_thread 提供了低级别的、原始的线程以及一个简单的锁,它相比于 threading 模块的功能还是比较有限的

threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法:

  • threading.currentThread(): 返回当前的线程变量。
  • threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
  • threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

线程共享全局变量

在一个进程内所有线程共享全局变量,多线程之间的数据共享比多进程要好。但是可能造成多个进程同时修改一个变量(即线程非安全),可能造成混乱。

互斥锁

如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。最简单的同步机制就是引入互斥锁

锁有两种状态——锁定和未锁定。某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”状态,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性

使用 Thread 对象的 Lock 可以实现简单的线程同步,有上锁 acquire 方法和 释放release 方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间。

死锁

在线程共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁

线程同步的应用

同步就是协同步调,按预定的先后次序进行运行。例如:开会。“同”字指协同、协助、互相配合。

如进程、线程同步,可以理解为进程或线程A和B一块配合,A执行到一定程度时要依靠B的某个结果,于是停下来,示意B运行,B运行后将结果给A,A继续运行

生产者消费者模式

生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入生产者和消费者模式

生产者消费者模式通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者之间不直接通信。生产者生产商品然后将其放到类似队列的数据结构中,消费者不找生产者要数据,而是直接从队列中取。这里使用queue模块来提供线程间通信的机制,也就是说,生产者和消费者共享一个队列。生产者生产商品后,会将商品添加到队列中。消费者消费商品,会从队列中取出商品。

ThreadLocal

我们知道多线程环境下,每一个线程均可以使用所属进程的全局变量。如果一个线程对全局变量进行了修改,将会影响到其他所有的线程对全局变量的计算操作,从而出现数据混乱,即为脏数据。为了避免多个线程同时对变量进行修改,引入了线程同步机制,通过互斥锁来控制对全局变量的访问。所以有时候线程使用局部变量比全局变量好,因为局部变量只有线程自身可以访问,同一个进程下的其他线程不可访问。

Python 还提供了ThreadLocal 变量,它本身是一个全局变量,但是每个线程却可以利用它来保存属于自己的私有数据,这些私有数据对其他线程也是不可见的

举个列子:

多线程示例:模拟下载网页数据

import threading
import time

# 模拟网页下载函数
def download_data(url, filename):
    print(f"Downloading data from {url}...")
    time.sleep(1)  # 模拟下载延迟
    data = f"Data from {url}"  # 模拟下载的数据
    write_to_file(filename, data)
    print(f"Finished downloading data from {url}")

# 文件写入函数(线程安全)
lock = threading.Lock()  # 用于线程同步

def write_to_file(filename, content):
    with lock:  # 确保每次只有一个线程能写入文件
        with open(filename, 'a') as f:
            f.write(content + '\n')

if __name__ == "__main__":
    filename = "web_data.txt"
    urls = [
        "http://example.com/page1",
        "http://example.com/page2",
        "http://example.com/page3",
        "http://example.com/page4",
        "http://example.com/page5"
    ]

    # 创建并启动多个线程,每个线程模拟下载不同网页
    threads = []
    for url in urls:
        t = threading.Thread(target=download_data, args=(url, filename))
        threads.append(t)
        t.start()

    # 等待所有线程完成
    for t in threads:
        t.join()

    # 读取并输出文件内容
    with open(filename, 'r') as f:
        content = f.read()
    print("\nFile content:\n", content)

线程的优点

1.多个线程共享当前进程的资源。
2.进程下的线程间通信,无需操作系统干预(进程通信需要请求操作系统服务CPU切换到内核态),开销更小。
3.线程间的并发比进程的开销更小,系统并发性提升。

需要注意的是:
1.从属于不同进程的线程间通信,也必须请求操作系统服务。
2.同样,从属于不同进程的线程间切换,它是会导致进程切换的,所以开销也大。

轻量级:线程的创建和销毁开销小,比进程快,因为线程共享同一进程的内存和资源。

通信简单:线程之间共享进程内存空间,数据交换无需复杂的机制,直接共享变量,通信效率高。

启动快:线程创建速度比进程快,适合频繁切换的任务。

资源占用少:线程共享进程的资源(如内存、文件句柄),能节省系统资源。

线程的特点

建、销毁和切换比进程更轻量、速度更快。

共享内存空间:同一进程内的所有线程共享相同的地址空间和资源(如内存、文件句柄等),这使得线程之间的数据共享和通信非常高效。

独立执行:每个线程有自己的运行栈和程序计数器,能独立执行任务,多个线程可以并发运行。

高效的上下文切换:由于线程共享进程的资源,上下文切换时不需要像进程那样保存和恢复大量的系统资源,切换的开销较小,效率高。

多线程并发:多线程允许在单核处理器上通过快速切换任务实现并发执行,在多核处理器上可实现真正的并行执行(除非有像Python的GIL限制)。

需要同步机制:由于线程共享资源,如果多个线程同时访问共享资源,可能会产生数据竞争和不一致,需要使用锁、信号量等同步机制来确保线程安全。

适合I/O密集型任务:由于I/O操作常常会导致阻塞,多线程可以在等待I/O操作时执行其他任务,充分利用资源,提高系统效率。

线程的缺点

当进程中的一个线程奔溃时,会导致其所属进程的所有线程奔溃。

线程安全问题:由于共享内存,多个线程同时访问数据时会产生竞争条件,必须使用锁等机制来避免数据冲突,增加了编程复杂度。

GIL限制(Python特有):Python中的全局解释器锁(GIL)限制了多线程在多核CPU上并行运行,无法提升CPU密集型任务的性能。

崩溃风险:线程共享内存,如果一个线程崩溃,可能导致整个进程崩溃,增加了系统不稳定的风险。

调试困难:线程间竞争和同步问题(如死锁、竞态条件)难以检测和调试。

 进程 VS 线程

一个进程中可以有多个线程,它们共享这个进程的资源(内存空间,包括代码段,数据集,堆等,及一些进程级的资源,如打开文件和信号等。为减少进程切换的开销,把进程作为资源分配的基本
单位(很少调度或切换),线程成为独立调度的基本单位,线程上下文切换比进程上下文切换要快得多。

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

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

相关文章

【Java数据结构】 链表

【本节目标】 1. ArrayList 的缺陷 2. 链表 3. 链表相关 oj题目 一. ArrayList的缺陷 上节课已经熟悉了ArrayList 的使用&#xff0c;并且进行了简单模拟实现。通过源码知道&#xff0c; ArrayList 底层使用数组来存储元素&#xff1a; public class ArrayList<E>…

探索Spring Boot:实现“衣依”服装电商平台

1系统概述 1.1 研究背景 如今互联网高速发展&#xff0c;网络遍布全球&#xff0c;通过互联网发布的消息能快而方便的传播到世界每个角落&#xff0c;并且互联网上能传播的信息也很广&#xff0c;比如文字、图片、声音、视频等。从而&#xff0c;这种种好处使得互联网成了信息传…

深入理解 CSS 浮动(Float):详尽指南

“批判他人总是想的太简单 剖析自己总是想的太困难” 文章目录 前言文章有误敬请斧正 不胜感恩&#xff01;目录1. 什么是 CSS 浮动&#xff1f;2. CSS 浮动的历史背景3. 基本用法float 属性值浮动元素的行为 4. 浮动对文档流的影响5. 清除浮动clear 属性清除浮动的技巧1. 使用…

从零开始讲PCIe(1)——PCI概述

一、前言 在之前的内容中&#xff0c;我们已经知道了PCIe是一种外设总线协议&#xff0c;其前身是PCI和PCI-X&#xff0c;虽然PCIe在硬件上有了很大的进步&#xff0c;但其使用的软件与PCI系统几乎保持不变。这种向后兼容性设计&#xff0c;目的是使从旧设计到新设计的迁移更加…

【QGis】生成规则网格/渔网(Fishnet)

【QGis】生成规则网格/渔网&#xff08;Fishnet&#xff09; QGis操作案例参考 QGIS下载安装及GIS4WRF插件导入可参见另一博客-【QGIS】软件下载安装及GIS4WRF插件使用。 QGis操作案例 1、加载中国省级边界&#xff0c;QGis界面如下&#xff1a; 查看坐标系&#xff1a; 如…

详解JVM类加载机制

❝ 前几篇文章我们分别详细描述了 JVM整体的内存结构 JVM对象内存是如何布局的以及内存分配的详细过程 但是对JVM内存结构各个模块没有深入的分析&#xff0c;为了熟悉JVM底层结构&#xff0c;接下来将把JVM运行时数据区的各个模块逐一分析&#xff0c;体系化的理解JVM的各个模…

【S32K3 RTD LLD篇5】K344 ADC SW+HW trigger

【S32K3 RTD LLD篇5】K344 ADC SWHW trigger 一&#xff0c;文档简介二&#xff0c;ADC SW HW 触发2.1 软硬件平台2.2 SWADC 软件触发2.3 SWBCTUADC 软件BCTU触发2.4 PITTRIGMUXADC 硬件PIT TRIGUMX触发2.5 EMIOSBCTUHWADC硬件EMIOS BCTU触发2.6 EMIOSBCTUHW LISTADC硬件EMIOS …

【计算机毕业设计】springboot游戏分享网站

摘 要 网络的广泛应用给生活带来了十分的便利。所以把游戏分享管理与现在网络相结合&#xff0c;利用java技术建设游戏分享网站&#xff0c;实现游戏分享的信息化。则对于进一步提高游戏分享管理发展&#xff0c;丰富游戏分享管理经验能起到不少的促进作用。 游戏分享网站能够…

Oracle架构之物理存储中各种文件详解

文章目录 1 物理存储1.1 简介1.2 数据文件&#xff08;data files&#xff09;1.2.1 定义1.2.2 分类1.2.2.1 系统数据文件1.2.2.2 撤销数据文件1.2.2.3 用户数据文件1.2.2.4 临时数据文件 1.3 控制文件&#xff08;Control files&#xff09;1.3.1 定义1.3.2 查看控制文件1.3.3…

【重学 MySQL】五十五、浮点和定点数据类型

【重学 MySQL】五十五、浮点和定点数据类型 种类选择数据精度说明浮点数据精度定点数据精度总结 精度误差说明浮点数据精度误差定点数据精度误差总结 示例注意事项开发中经验 在MySQL中&#xff0c;浮点和定点数据类型用于存储小数和实数。 种类 MySQL提供了两种主要的浮点数…

SuiteCRM系统 responseEntryPoint SQL注入复现(CVE-2024-36412)

0x01 产品描述&#xff1a; SuiteCRM是一款开源的CRM&#xff08;客户关系管理&#xff09;系统&#xff0c;它致力于为世界各地的用户提供高效、灵活和可定制的CRM解决方案。它为企业和组织提供了一套完整的客户关系管理解决方案&#xff0c;无论是中小型企业还是大型企业&…

Python和R及Julia妊娠相关疾病生物剖析算法

&#x1f3af;要点 算法使用了矢量投影、现代优化线性代数、空间分区技术和大数据编程利用相应向量空间中标量积和欧几里得距离的紧密关系来计算使用妊娠相关疾病&#xff08;先兆子痫&#xff09;、健康妊娠和癌症测试算法模型使用相关性投影利用相关性和欧几里得距离之间的关…

linux第二课:常用命令

Kali Linux&#xff0c;黑客必备神器。跟着我&#xff0c;带你从入门到入狱&#xff01; 第二课&#xff0c;常用命令。 1.whoami 翻译为中文&#xff1a;我是谁 用途&#xff1a;输出现在自己的用户身份(用户名) 参数&#xff1a;无参数 好吧&#xff0c;这透明度一调都不…

基于SpringBoot+Vue的汽车保险理赔系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

mysql UDF提权(实战案例)

作者&#xff1a;程序那点事儿 日期&#xff1a;2024/09/29 16:10 什么是UDF? 全称 User Define Function &#xff08;用户自定义函数&#xff09;UDF提权&#xff0c;就是通过自定义函数&#xff0c;实现执行系统的命令。 dll&#xff08;windows&#xff0c;dll文件是c语…

10.1 10.3 图DFS 中等 207 Course Schedule 210 Course Schedule Ⅱ

207 Course Schedule class Solution { public:bool hasCycle(int course ,unordered_map<int,vector<int>>& graph,vector<int>& visitStatus){//正在访问的结点再次被访问&#xff0c;存在环if(visitStatus[course] 1)return true;//该结点已经被…

【CViT】Deepfake Video Detection Using Convolutional Vision Transformer

文章目录 Deepfake Video Detection Using Convolutional Vision Transformerkey points**卷积视觉变压器**FLViT实验总结Deepfake Video Detection Using Convolutional Vision Transformer 会议/期刊:2021 作者: key points 提出了一种用于检测深度伪造的卷积视觉变压器…

Linux学习之路 -- 线程 -- 死锁及线程安全相关问题

在上文中&#xff0c;我们已经介绍了线程池的编写&#xff0c;下面补充一下线程的相关知识。 目录 1、线程安全与可重入 <1>概念 <2>区别联系 <3>常见线程不安全的情况 <4>常见的不可重入情况 2、死锁问题 <1>死锁概念 <2>死锁四…

sql-labs靶场第二关测试报告

目录 一、测试环境 1、系统环境 2、使用工具/软件 二、测试目的 三、操作过程 1、寻找注入点 2、注入数据库 ①Order by判断列数 ②判断回显地方 ③爆库&#xff0c;查看数据库名称 ④爆表&#xff0c;查看security库的所有表 ⑤爆列&#xff0c;查看users表的所有…

Redis-哨兵

概念 Redis Sentinel 相关名词解释 注意: 哨兵机制不负责存储数据,只是对其它的redis-server进程起到监控的作用哨兵节点,也会搞一个集合,防止一个挂了 ⼈⼯恢复主节点故障 用户监控: 实际开发中,对于服务器后端开发,监控程序,是很重要的 服务器长期运行,总会有一些意外,…