Python语法进阶学习--进程和线程

后续很快就要进入Spark的学习,在学习之前也是要铺垫一个知识点:进程是什么?线程是什么?两者有什么区别?又有什么关系?

一. 并发与并行

  • 并发:在一段时间内快速交替去执行多个任务(多线程)
  • 并行:在一段时间内真正的同时一起执行多个任务(多进程)

二. 进程(Process)

  • 是操作系统进行资源分配的基本单位
  • 进程可以有一个或多个子进程
  • 最原始的父进程是由操作系统提供的
  • 进程之间不共享变量
  • 子进程可以设置为守护进程
  • 主进程主动终止子进程

多线程示例

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('主进程结束!')

子进程设为守护进程示例

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

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('主进程结束!')

主进程终止子进程

子进程被动结束

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()

三. 线程(Thread)

  • 是CPU进行调度的基本单位
  • 线程可以有一个或多个子线程
  • 线程是由进程主动创建出来的,创建第一次创建子线程时才会出现主线程
  • 线程共用全局变量

多线程示例

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)

四. 资源共享的注意点

线程的资源共享问题(只存在于低版本的Python解释器比如3.6.5,3.10已解决):当多个线程同时操作同一个共享的全局变量时,可能会造成错误的结果,解决办法如下

  • 线程同步:保证同一时刻只能有一个线程去操作共享资源(全局变量)
    • 线程等待thread.join()
      • 让一个线程完全执行结束,再去执行另一个线程
      • 缺点:一个执行完再执行另一个,和单任务几乎没有区别
    • 互斥锁:
      • 多个线程去抢同一把"锁",threading.Lock()抢到锁的线程执行,没抢到锁的线程会阻塞等待。
      • 缺点:虽然保障程序执行的多任务,如果频繁的加锁、释放锁会额外增加执行的时间消耗
  • 从场景下手:不用多线程做累加count操作,只做append操作!

五. 进程线程对比

  • 进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位。
  • 线程不能够独立执行,必须依存在进程中。
  • 创建进程的资源开销要比创建线程的资源开销要大。
  • 进程之间不共享全局变量,线程之间共享全局变量,但是在低版本的Python中要注意线程资源竞争的问题。
  • 进程稳定性高,适合计算密集型任务;线程适合IO密集型任务
  • 目前Python多线程不能利用CPU多核心优势,想利用CPU多核心的优势,Python只能采用多进程

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

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

相关文章

DHCP自动获取实验和DNS正向解析实验

一、服务程序 1.1DHCP定义 DHCP(动态主机配置协议)是一个局域网的网络协议。指的是由服务器控制一段IP地址范围,客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码。默认情况下,DHCP作为Windows Server的一个服务组…

flex布局 子元素无限撑大元素问题解决

flex 布局下,使用flex:xx 的子项无限撑大容器 祖先容器使用flex布局,父容器使用flex:xx的时候,此时如果父容器下的子项使用宽高100%,子项将会无限撑大容器。 解决办法: 祖先容器使用flex定位时…

基于JavaWeb+BS架构+SpringBoot+Vue电影订票系统系统的设计和实现

基于JavaWebBS架构SpringBootVue电影订票系统系统的设计和实现 文末获取源码Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 文末获取源码 Lun文目录 1 绪 论 3 1.1研究背景和意义 3 1.2拟解决的问题及特性 3 1.3论文的结构 …

目标检测中的数据增强

整个代码参考:bubbliiiing/object-detection-augmentation。 random_data.py import cv2 import numpy as np from PIL import Image, ImageDrawdef rand(a=0, b=1):return np.random.rand()*(b-a) + adef get_random_data(annotation_line, input_shape, jitter=.3, hue=.1…

【蓝桥杯/DFS】路径之谜 (Java)

路径之谜小明冒充X星球的骑士,进入了一个奇怪的城堡。 城堡里边什么都没有,只有方形石头铺成的地面。假设城堡地面是 n x n 个方格。【如图1.png】所示。按习俗,骑士要从西北角走到东南角。 可以横向或纵向移动,但不能斜着走&…

vue本地运行开发,为什么要配置changeOrigin: true

changeOrigin: true是在配置反向代理时常见的一个选项,通常用于解决跨域请求的问题。Vue本地运行时,可能会涉及到前端应用与后端服务不在同一个域的情况,这就会触发浏览器的同源策略,阻止跨域请求。 使用Vue CLI(或其…

下一代 Vue3 Devtools 正式开源

什么是 Vue DevTools Vue DevTools 是一个旨在增强 Vue 开发人员体验的工具,它提供了一些功能来帮助开发者更好地了解 Vue 应用程序。 Vue DevTools:Unleash Vue Developer Experience. Enhance your Vue development journey with an amazing experience! 典型的功能特征包…

50天精通Golang(第14天)

一、数据库 1.1 数据库 基本知识 DB: DBMS: 数据库,数据表,表的结构。。 DB:是指datebase(数据库) 数据库是存储数据的一个集合,数据库中通常使用数据表等组成,而数…

3d云渲染用什么显卡比较好?3d云渲染显卡推荐

3D云渲染能加快渲染速度,是众多公司的首选方案,作为公司负责人,选择哪个平台值得思考,今天我就说下我的选择吧。 首先我们要了解云渲染的渲染方式,云渲染的渲染方式分两种,一种是CPU渲染,一种是…

linux下编译ffmpeg 以及交叉编译并引入Android

linux下编译ffmpeg 下载: http://ffmpeg.org/download.html 支持mp3编码:ffmpeg自身只支持mp3的解码但是不支持mp3的编码,如果希望格式转换为mp3,我们可以先安装支持库lame:(使用时: ffmpeg -i audio.wav -acodec libmp3lame audio.mp3) #…

openssl3.2 - 官方demo学习 - keyexch - x25519.c

文章目录 openssl3.2 - 官方demo学习 - keyexch - x25519.c概述笔记END openssl3.2 - 官方demo学习 - keyexch - x25519.c 概述 官方程序中演示了私钥2种key交换的情况: 产生X25519的key对(私钥/公钥), 并交换公钥给对方, 并分别产生会话密钥, 使双方都能持有相同的会话密钥 …

PHP AES加解密示例

以下是一个使用PHP的openssl扩展进行AES加密和解密的示例代码&#xff1a; php复制代码 <?php // 密钥和初始向量 $key your_secret_key; $iv your_initial_vector; // 加密函数 function encryptAES($data, $key, $iv) { $encrypted openssl_encrypt($data, AES-256-C…

解读Vue的原型及原型链

在 JavaScript 中&#xff0c;每个对象都有一个关联的原型&#xff08;prototype&#xff09;。原型是一个对象&#xff0c;其他对象可以通过原型实现属性和方法的继承。原型链是一种由对象组成的链式结构&#xff0c;它通过原型的引用连接了一系列对象&#xff0c;形成了一种继…

克服大模型(LLM)部署障碍,全面理解LLM当前状态

近日&#xff0c;CMU Catalyst 团队推出了一篇关于高效 LLM 推理的综述&#xff0c;覆盖了 300 余篇相关论文&#xff0c;从 MLSys 的研究视角介绍了算法创新和系统优化两个方面的相关进展。 在人工智能&#xff08;AI&#xff09;的快速发展背景下&#xff0c;大语言模型&…

从文本文件或 csv 文件读取信息的示例

如下表格说明文本文件或 csv 文件中的信息如何在 WinCC (TIA Portal) 中显示。 IO 域用作于显示&#xff0c;只有最有一个条目被输出。 注意 在此例中由于最后一条条目被搜索&#xff0c;脚本的运行系统会随着文件的尺寸增长而增长。先前示例中的配置在该示例中不是必须的。但是…

Linux 系统上,你可以使用 cron 定时任务来定期备份 MySQL 数据库

在 Linux 系统上&#xff0c;你可以使用 cron 定时任务来定期备份 MySQL 数据库。以下是一个基本的步骤&#xff0c;假设你已经安装了 MySQL 数据库和使用了 mysqldump 工具来进行备份。 步骤&#xff1a; 创建备份脚本&#xff1a; 创建一个包含备份命令的脚本。在这个例子中…

leetcode 1两数之和

题目 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可以按任意顺…

手把手教你使用Django如何连接Mysql

目录 一、引言 二、准备工作 三、配置Django连接MySQL 1、安装MySQL驱动&#xff1a; 2、配置数据库设置&#xff1a; 3、 创建数据库迁移&#xff1a; 四、编写Django模型和视图函数 1、编写模型&#xff1a; 2. 编写视图函数&#xff1a; 3. 编写模板&#xff1a; …

前端解析文件流

第一种方法&#xff0c;转blob对象 this.$axios({url: /md2api/attachment/c/${val.code},method: "GET",responseType: blob, //设置响应格式headers: {"Content-Type": "application/x-www-form-urlencoded",}, }) .then(function (respons…

软件测试感悟2

沟通 a.在测试前期与开发沟通&#xff0c;确认测试重点 &#xff0c;确认测试的优先级 b.了解开发人员技术和业务背景 业务水平 技术水平 代码质量 人员流动性 在测试结束后 对已发现的bug进行统计 ,知道高发概率bug ,在新项目中要进行重点测试 针对代码 代码复杂…