Python---多进程---多线程

总结

1- 多进程:计算机分配资源的最小单位。
2- 多线程:CPU进行任务切换的最小单位。
3- 线程不能独立存在,必须存在在进程中。
4- 多进程中,多个子进程和主进程间,不会共享全局变量
5- 多线程中,多个子线程和主线程间,会共享全局变量
6- 将子线程,标记为守护线程。只有设置为守护线程的,才会在主线程运行结束后,跟着结束。否则不受任何影响

  • 并发与并行
    • 并发:在一段时间内快速交替去执行多个任务(多线程)
    • 并行:在一段时间内真正的同时一起执行多个任务(多进程)
  • 进程(Process)
    • 是操作系统进行资源分配的基本单位
    • 进程可以有一个或多个子进程
    • 最原始的父进程是由操作系统提供的
  • 线程(Thread)
    • 是CPU进行调度的基本单位
    • 线程可以有一个或多个子线程
    • 线程是由进程主动创建出来的,创建第一次创建子线程时才会出现主线程
  • 线程的资源共享问题(只存在于低版本的Python解释器比如3.6.5,3.10已解决):当多个线程同时操作同一个共享的全局变量时,可能会造成错误的结果,解决办法如下
    • 线程同步:保证同一时刻只能有一个线程去操作共享资源(全局变量)
      • 线程等待thread.join()
        • 让一个线程完全执行结束,再去执行另一个线程
        • 缺点:一个执行完再执行另一个,和单任务几乎没有区别
      • 互斥锁:
        • 多个线程去抢同一把"锁",threading.Lock()抢到锁的线程执行,没抢到锁的线程会阻塞等待。
        • 缺点:虽然保障程序执行的多任务,如果频繁的加锁、释放锁会额外增加执行的时间消耗
    • 从场景下手:不用多线程做累加count操作,只做append操作!
  • 进程线程对比
    • 进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位。
    • 线程不能够独立执行,必须依存在进程中。
    • 创建进程的资源开销要比创建线程的资源开销要大。
    • 进程之间不共享全局变量,线程之间共享全局变量,但是在低版本的Python中要注意线程资源竞争的问题。
    • 进程稳定性高,适合计算密集型任务;线程适合IO密集型任务
    • 目前Python多线程不能利用CPU多核心优势,想利用CPU多核心的优势,Python只能采用多进程

多进程

多进程实例

import time
import os
import multiprocessing
# os.getpid():process id,获取进程的编号
# os.getppid():parent process id,获取父进程编号# 跳舞函数
def dance():print(f'dance进程的编号:{os.getpid()},父进程编号:{os.getppid()}')for i in range(5):print('跳舞中...')# 休眠1秒钟time.sleep(1)# 唱歌函数
def sing():print(f'sing进程的编号:{os.getpid()},父进程编号:{os.getppid()}')for i in range(5):print('唱歌中...')# 休眠1秒钟time.sleep(1)if __name__ == '__main__':# 最原始的父进程是由操作系统提供的print(f'主进程的编号为:{os.getpid()},父进程编号:{os.getppid()}')# 创建两个进程,一个执行 dance 函数,另一个执行 sing 函数dance_process = multiprocessing.Process(target=dance)sing_process = multiprocessing.Process(target=sing)# 启动进程dance_process.start()sing_process.start()

多进程执行带有参数的任务

import multiprocessing
import time# 带有参数的任务(函数)
def task(count):for i in range(count):print('任务执行中...')time.sleep(0.2)else:print('任务执行完成')if __name__ == '__main__':# 传参方式1 args=(参数值1, ...)# task_process = multiprocessing.Process(target=task, args=(3,))# 传参方式2 kwargs={'形参字符串1': 值1, '形参字符串2': 值2, ...}task_process = multiprocessing.Process(target=task, kwargs={'count': 5})# 启动进程task_process.start()task_process.join()print('这行代码一定等task_process进程执行完毕之后才会运行,打印')

多进程之间不共享变量

import multiprocessing
import time# 定义全局变量
g_list = []# 添加数据的函数
def add_data():for i in range(5):g_list.append(i)print('add:', i)time.sleep(0.2)print('add:', g_list)# 读取数据的函数
def read_data():print('read:', g_list)if __name__ == '__main__':# 创建添加数据的子进程add_data_process = multiprocessing.Process(target=add_data)# 创建读取数据的子进程read_data_process = multiprocessing.Process(target=read_data)# 启动添加数据子进程add_data_process.start()# 阻塞等待:主进程等待 add_data_process 执行完成,再向下继续执行add_data_process.join()# 启动读取数据子进程read_data_process.start()# 主进程读取数据print('main:', g_list)# 主进程延时 1stime.sleep(1)print('主进程结束!')

子进程设置为守护进程

主进程结束,设为守护进程的子进程主动GG

import multiprocessing
import timedef task():for i in range(10):print('任务执行中...')time.sleep(0.5)if __name__ == '__main__':# 创建子进程并启动sub_process = multiprocessing.Process(target=task)# TODO:设置子进程为守护进程sub_process.daemon = Truesub_process.start()# 主进程延时 1stime.sleep(1)print('主进程结束!')

主进程终止子进程

子进程被动GG

import multiprocessing
import time# 任务函数
def task():for i in range(10):print('任务执行中...')time.sleep(0.5)if __name__ == '__main__':# 创建子进程并启动sub_process = multiprocessing.Process(target=task)sub_process.start()# 主进程延时 1stime.sleep(1)print('主进程结束!')# TODO: 终止子进程sub_process.terminate()

多线程

多线程实例

import time
import threading# 跳舞函数
def dance(num):for i in range(num):print('跳舞中...')time.sleep(1)# 唱歌函数
def sing(num):for i in range(num):print('唱歌中...')time.sleep(1)if __name__ == '__main__':# 创建两个线程,分别执行 dance 和 singdance_thread = threading.Thread(target=dance, args=(5,))sing_thread = threading.Thread(target=sing, kwargs={'num':5})# 启动线程dance_thread.start()sing_thread.start()

线程共用全局变量

import threading
import time# 定义全局变量
g_list = []# 添加数据的函数
def add_data():for i in range(5):g_list.append(i)print('add:', i)time.sleep(0.2)print('add:', g_list)# 读取数据的函数
def read_data():print('read:', g_list)if __name__ == '__main__':# 创建添加数据的子线程add_data_thread = threading.Thread(target=add_data)# 创建读取数据的子线程read_data_thread = threading.Thread(target=read_data)# 启动添加数据子线程add_data_thread.start()# 阻塞等待:主线程等待 add_data_thread 执行完成,再向下继续执行add_data_thread.join()# 启动读取数据子线程read_data_thread.start()# 阻塞等待:主线程等待 read_data_thread 执行完成,再向下继续执行read_data_thread.join()print('main:', g_list)

join()使用总结:
1- 作用:线程等待子线程执行结束
2- 使用场景:主线程需要使用多个子线程运行的最终结果,才能够继续往下运行。
举例:吃火锅,张三叫李四带点食材,并且张三叫王五带锅。有了锅和食材以后,才能够开始煮火锅

线程互斥锁

注释lock锁相关代码,并使用 低版本的Python解释器(python3.6.5) 才能看到线程资源安全问题的效果!Python 3.10 已经解决了该问题!

# 互斥锁:多个线程去抢同一把"锁",抢到锁的线程执行,没抢到锁的线程会阻塞等待
import threading# 定义全局变量
g_num = 0# 创建一个多线程互斥锁
lock = threading.Lock()def sum_num1():global g_num# 循环一次给全局变量加1for i in range(1000000):# 抢到锁,代码可以继续向下执行,否则就会阻塞等待lock.acquire() # 抢锁g_num += 1lock.release() # 释放锁print('sum1:', g_num)def sum_num2():global g_num# 循环一次给全局变量加1for i in range(1000000):# 抢到锁,代码可以继续向下执行,否则就会阻塞等待lock.acquire() # 抢锁g_num += 1lock.release() # 释放锁print('sum2:', g_num)if __name__ == '__main__':# 创建两个线程first_thread = threading.Thread(target=sum_num1)second_thread = threading.Thread(target=sum_num2)# 启动两个线程first_thread.start()second_thread.start()# 阻塞等待:主线程等待子线程结束再向下运行first_thread.join()second_thread.join()print(g_num)

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

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

相关文章

考研后SpringBoot复习1

考研后SpringBoot复习 Hello World入门 复习的版本为SpringBoot2的版本 创建maven项目 在pom文件中导入SpringBoot的依赖同时引入web开发的启动器 <!--声明springboot父项目--><parent><groupId>org.springframework.boot</groupId><artifactId>…

【大模型的前世今生】从自然语言处理说起

自然语言处理&#xff08;Natural Language Processing&#xff0c;简称NLP&#xff09;被誉为人工智能皇冠上的明珠&#xff0c;是计算机科学和人工智能领域的一个重要方向。它主要研究人与计算机之间&#xff0c;使用自然语言进行有效通信的各种理论和方法。简单来说&#xf…

AcWing算法提高课-2.3.1矩阵距离

算法提高课整理 CSDN个人主页&#xff1a;更好的阅读体验 本文同步发表于 CSDN | 洛谷 | AcWing | 个人博客 原题链接 题目描述 给定一个 01 矩阵&#xff0c;求矩阵中每个元素离 1 的最短曼哈顿距离。 输入格式 第一行两个整数 n , m n,m n,m。 接下来一个 n n n 行 …

hadoop hive spark flink 安装

下载地址 Index of /dist ubuntu安装hadoop集群 准备 IP地址主机名称192.168.1.21node1192.168.1.22node2192.168.1.23node3 上传 hadoop-3.3.5.tar.gz、jdk-8u391-linux-x64.tar.gz JDK环境 node1、node2、node3三个节点 解压 tar -zxvf jdk-8u391-linux-x64.tar.gz…

分布式文件系统的介绍

什么是分布式文件系统 跨越多个服务器或者多个位置的文件系统。其中涉及的技术包括数据的复制、数据的分片和路由,由于用户可能存储大文件、图片或者其他类似的需求性文件,因此需要设计不同的系统方便用户访问的存取。 任何设备通过任何网络位置访问文件,就像访问到自己的文…

GitHub Copilot 快速入门指南

GitHub Copilot 快速入门指南 GitHub Copilot 是由 GitHub 推出的一款人工智能编程助手&#xff0c;基于 OpenAI 提供的 GPT-3 技术构建。GitHub Copilot 能够根据你编写的注释和代码自动生成代码建议&#xff0c;并且支持多种编程语言。本文将作为一个快速入门指南&#xff0…

华清远见作业第十六天

思维导图&#xff1a; 双向循环链表头插入&#xff1a; 代码&#xff1a; Doublelist insert_head(Doublelist head,datatype element) {//创建新节点sDoublelist screate_node();if(NULLs){return head;}s->dataelement;//数据存储//判断链表是否为空if(NULLhead){heads;…

性能测试-jmeter:安装 / 基础使用

一、理解jmeter 官网-Apache JMeter-Apache JMeter™ JMeter是一款开源的性能测试工具&#xff0c;主要用于模拟大量用户并发访问目标服务器&#xff0c;以评估服务器的性能和稳定性。 JMeter可以执行以下任务序号用途描述1性能测试通过模拟多个用户在同一时间对服务器进行请…

limit查询报错问题

分页时候 limit 后面的公式是 (pageNum-1)*pageSize,pageSize 但是在数据库查询时候 当然在.XML中也不能像下面这么写,如果要计算 在业务层或者控制层计算好再传值进来

RAID的介绍和选择

RAID 类型&#xff1a;什么是 RAID 以及哪种 RAID 级别适合您&#xff1f; 一、RAID 简介 在2021年6月11日&#xff0c;亚瑟迪特纳进行了一场关于RAID技术的技术讲座。RAID&#xff0c;即独立磁盘冗余阵列&#xff0c;是将多个硬盘驱动器协同工作的技术。不同的RAID类型各有优…

独立站的设计美学:用户体验的核心要素

随着互联网的普及和发展&#xff0c;独立站已经成为越来越多企业的营销策略之一。独立站的设计美学不仅仅是外观的美观&#xff0c;更是用户体验的核心要素。本文将探讨独立站的设计美学及其对用户体验的影响&#xff0c;并介绍如何通过代码实现美观的网页设计。 一、独立站的设…

安装ps提示msvcr71.dll丢失的解决方法,全面解析dll问题

当您在安装PS软件时遇到msvcr71.dll丢失的问题&#xff0c;这是因为该文件是某些程序运行必需的。msvcr71.dll主要包含了C运行时库的函数&#xff0c;这些函数主要用于处理字符串、数学运算、内存管理等基本操作。例如&#xff0c;我们在编写程序时&#xff0c;需要对字符串进行…

【STM32】STM32学习笔记-PWM驱动LED呼吸灯 舵机 直流电机(16)

00. 目录 文章目录 00. 目录01. 输出比较相关API1.1 TIM_OC1Init1.2 TIM_OCInitTypeDef结构体1.3 TIM_OCMode1.4 TIM_OutputState1.5 TIM_OutputNState1.6 TIM_OCPolarity1.7 TIM_OCNPolarity1.8 TIM_OCPolarity1.9 TIM_OCNPolarity 02. PWM实现呼吸灯接线图03. PWM实现呼吸灯示…

深入理解Vue.js 3的Reactive方法

Vue.js 3引入了Composition API&#xff0c;这是一次对Vue开发模式的重大革新&#xff0c;它为我们提供了更灵活、更强大的代码组织方式。今天&#xff0c;我们将深入探讨其中的核心功能之一——reactive方法。我们将了解它是什么&#xff0c;如何使用它&#xff0c;以及一些使…

基于C语言的数学四则运算程序(选择语句)

程序如下 #include <stdio.h>int main() { char operator; double num1, num2, result; printf("请输入运算符 (, -, *, /): "); scanf("%c", &operator); printf("请输入两个数字&#xff0c;用空格分隔: &…

WAZUH的安装、设置代理

wazuh安装 wazu的安装分为以下两种方式 官方文档&#xff1a;https://wazuh.com/blog/detecting-common-linux-persistence-techniques-with-wazuh/ 1、自定义安装 这种方式就是一步一步的安装 直接参考官方文档&#xff1a; 这里就不详细介绍了&#xff0c;本次主要介绍的…

【Java开发岗面试】八股文—数据库MySQLRedis

声明&#xff1a; 背景&#xff1a;本人为24届双非硕校招生&#xff0c;已经完整经历了一次秋招&#xff0c;拿到了三个offer。本专题旨在分享自己的一些Java开发岗面试经验&#xff08;主要是校招&#xff09;&#xff0c;包括我自己总结的八股文、算法、项目介绍、HR面和面试…

FreeRTOS 实时操作系统第八讲 - 时间管理 (系统节拍,延时函数)

一、系统节拍 FreeRTOS 实时操作系统需要一个时钟节拍&#xff0c;以供系统处理诸如延时、超时、软件定时器等与时间相关的事件。 时钟节拍是周期性定时中断&#xff0c;这个中断可以看做是系统心跳。中断时间间隔取决于不同的应用&#xff0c;一般是 1ms – 100ms。时钟的节拍…

[C#]C# winform实现imagecaption图像生成描述图文描述生成

介绍&#xff1a; 地址&#xff1a;C#https://github.com/ruotianluo/ImageCaptioning.pytorch 效果&#xff1a; 测试环境&#xff1a; vs2019 onnxruntime1.16.3 opencvsharp4.8 代码&#xff1a; using System; using System.Collections.Generic; using System.Comp…

学习体系结构 - AArch64内存管理

学习体系结构 - AArch64内存管理 Learn the architecture - AArch64 memory management Version 1.2 个人的英语很一般&#xff0c;对拿不准的翻译校准在后面添加了英文原文。 1、 概述 本指南介绍了AArch64中的内存转换&#xff0c;这是内存管理的关键。它解释了如何将虚拟地…