Python进程与线程开发

目录

multiprocessing模块

线程的开发

threading模块 

 setDaemon

死锁 

 线程间的通信


multiprocessing模块

运行python的时候,我们都是在创建并运行一个进程,(linux中一个进程可以fork一个子进程,并让这个子进程exec另外一个程序)。在python中,我们通过标准库中的subprocess包来fork一个子进程,并且运行一个外部的程序。subprocess包中定义有数个创建子进程的函数,这些函数分别以不同的方式创建子进程,所欲我们可以根据需要来从中选取一个使用。另外subprocess还提供了一些管理标准流(standard stream)和管道(pipe)的工具,从而在进程间使用文本通信。

multiprocessing 包同时提供本地和远程并发,使用子进程代替线程,有效避免 Global Interpreter Lock 带来的影响。

from multiprocessing import Process
import os
from time import sleep, time
def test1(name):print("当前进程的ID", os.getpid())print("父进程的ID", os.getppid())print("当前进程的名字:", name)sleep(3)if __name__ == '__main__':start = time()# 创建多个子进程,并且把这些子进程放入列表中process_list = []print("主进程的ID", os.getpid())for i in range(10):p = Process(target=test1, args=('process-%s' % i,))p.start()process_list.append(p)

类包装:自定义一个Process进程类,该类中的run函数由一个子进程调用执行

from multiprocessing import Process
import os
from time import sleep, time
# 自定义一个进程类 继承Process类
class MyProcess(Process):def __init__(self, name):Process.__init__(self)self.name = namedef run(self):print("当前进程的ID", os.getpid())print("父进程的ID", os.getppid())print("当前进程的名字:", self.name)sleep(3)if __name__ == '__main__':print("主进程ID", os.getpid())start = time()process_list = []for i in range(10):p = MyProcess("process-%s" % i)p.start()process_list.append(p)for p in process_list:p.join()end = time() - startprint(end)

线程的开发

Python 的标准库提供了两个模块:thread 和 threading,thread 是低级模块,threading 是高级模块,对_thread进行了封装。绝大多数情况下,我们只需要使用threading 这个高级模块。

多线程概念

多线程使得系统可以在单独的进程中执行并发任务。虽然进程也可以在独立的内存空间中并发执行,但是其系统开销会比较大。生成一个新进程必须为其分配独立的地址空间,并维护其代码段、堆栈段和数据段等,这种开销是巨大的。另外,进程间的通信实现也不方便。在程序功能日益复杂的时候,需要有更好的系统模型来满足要求,线程由此产生了。 线程是“轻量级”的,一个进程中的线程使用同样的地址空间,且共享许多资源。启动线程的时间远远小于启动进程的时间和空间,而且,线程间的切换也要比进程间的切换快得多。由于使用同样的地址空间,所以线程之间的数据通信比较方便,一个进程下的线程之间可以直接使用彼此的数据。当然,这种方便性也会带来一些问
题,特别是同步问题。 多线程对于那些I/O受限的程序特别适用。其实使用多线程的一个重要目的,就是最大化地利用CPU的资源。当某一线程在等待I/O的时候,另外一个线程可以占用CPU资源。如最简单的GUI程序,一般需要有一个任务支持前台界面的交互,还要有一个任务支持后台的处理。 

多线程运行的作用:

  • 使用线程可以把占据长时间的程序中的任务放到后台去处理。
  • 用户界面可以更加吸引人,比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度。
  • 程序的运行速度可能加快。
  • 在一些等待的任务实现上如用户输入、文件读写和网络收发数据等。在这种情况下我们可以释放一些珍贵的资源如内存占用。 

线程可以分为内核线程和用户线程,内核线程由操作系统内核创建和撤销;用户线程不需要内核支持而在用户程序中实现的线程。

创建线程 

Python3 通过两个标准库 _thread 和 threading 提供对线程的支持。

threading模块 

import time
def say():print("这是单线程!")time.sleep(1)
if __name__ == "__main__":start = time.time()for i in range(5):say()end = time.time()print(f'使用时间:{end - start}')
import threading
import time
def say():print("这是多线程")time.sleep(1)
if __name__ == "__main__":'''入口'''start = time.time()for i in range(5):# 通过threading下的Thread方法创建线程t = threading.Thread(target=say)t.start()  # 启动线程end = time.time()print(f'使用时间:{end - start}')

 可以明显看出使用了多线程并发的操作,花费时间要短很多。

程序是通过threading模块下的Thread的类,去实例化一个此对象,并调用方法,实现生成多线程,target参数表示线程需要执行的方法,通过对象的start的方法,开启线程。

import threading
from time import sleep,ctime
def sing():for i in range(3):print("唱歌...%d"%i)sleep(1)
def dance():for i in range(3):print("跳舞...%d"%i)sleep(1)
if __name__ == '__main__':print('---开始---:%s'%ctime())t1 = threading.Thread(target=sing)t2 = threading.Thread(target=dance)t1.start()t2.start()sleep(5) print('---结束---:%s'%ctime())

 join方法

该方法将等待,一直到它调用的线程终止,它的名字表示调用的线程会一直等待,直到指定的线程加入它。join所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程再终止。

from threading import Thread
from time import sleep, time
def run(name):print("Threading:{} start".format(name))sleep(3)print("Threading:{} end".format(name))
if __name__ == '__main__':# 开始时间start = time()# 创建线程列表t_list = []# 循环创建线程for i in range(10):t = Thread(target=run, args=('t{}'.format(i),))t.start()t_list.append(t)# 等待线程结束for t in t_list:t.join()# 计算使用时间end = time() - startprint(end)

 setDaemon

将线程声明为守护线程,在start() 方法调用之前设置,这个方法和join是相反的。

有时候我们需要的是 只要主线程完成了,不管子线程是否完成,都要和主线程一起退出,
这时就可以用setDaemon方法。

from threading import Thread
import time
def foo():print(123)time.sleep(1)print("end123")
def bar():print(456)time.sleep(3)print("end456")
t1 = Thread(target=foo)
t2 = Thread(target=bar)
t1.daemon = True
t1.start()
t2.start()
print("~~~")

同步锁与GIL的关系 

GIL本质是一把互斥锁,但GIL锁住的是解释器级别的数据,同步锁,锁的是解释器以外的共享资源,例如:硬盘上的文件 控制台,对于这种不属于解释器的数据资源就应该自己加锁处理 。

GIL 的作用是:对于一个解释器,只能有一个thread在执行bytecode。所以每时每刻只有一条bytecode在被执行一个thread。GIL保证了bytecode 这层面上是thread safe的。

死锁 

在多线程程序中,死锁问题很大一部分是由于线程同时获取多个锁造成的。
在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。 

产生死锁的四个必要条件:

  • 互斥条件:一个资源每次只能被一个线程使用。
  • 请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放。
  • 不剥夺条件:线程已获得的资源,在末使用完之前,不能强行剥夺。
  • 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。 
from threading import Thread,Lock
from time import sleep
class Task1(Thread):def run(self):while True:if lock1.acquire():print("------Task 1 -----")sleep(0.5)lock2.release()
class Task2(Thread):def run(self):while True:if lock2.acquire():print("------Task 2 -----")sleep(0.5)lock3.release()class Task3(Thread):def run(self):while True:if lock3.acquire():print("------Task 3 -----")sleep(0.5)lock1.release()lock1 = Lock()
#创建另外一把锁
lock2 = Lock()
lock2.acquire()lock3 = Lock()
lock3.acquire()
t1 = Task1()
t2 = Task2()
t3 = Task3()
t1.start()
t2.start()
t3.start()

 线程间的通信

在加锁的情况下,程序就变成了串行,也就是单线程,而有时,我们在不用考虑数据安全时,不用加锁,程序就变成了并行,也就是多线程。为了避免业务开启过多的线程时。我们就可以通过信号量(Semaphore)来设置指定个数的线程。 

from threading import Thread, BoundedSemaphore
from time import sleep
def an_jian(num):semapshore.acquire()print('第{}个人安检完成!'.format(num))sleep(2)semapshore.release()if __name__ == '__main__':semapshore = BoundedSemaphore(3)for i in range(20):thread = Thread(target=an_jian, args=(i,))thread.start()

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

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

相关文章

机器学习——压缩网络作业

文章目录 任务描述介绍知识蒸馏网络设计 Baseline实践 任务描述 网络压缩:使用小模型模拟大模型的预测/准确性。在这个任务中,需要训练一个非常小的模型来完成HW3,即在food-11数据集上进行分类。 介绍 有许多种网络/模型压缩的类型&#xff0…

Java并发

目录 线程 什么是线程 进程和线程的区别 线程的生命周期 什么是多线程 并发与并行 多线程的三种实现方式 继承Thread类 1.创建类继承Thread类 2.重写run()方法 3.创建对象启动线程 实现Runnable接口 1.自己定义一个类实现Runnable接口 2.重…

由浅到深认识C语言(14):枚举

该文章Github地址:https://github.com/AntonyCheng/c-notes 在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址:https://blog.csdn…

python毕业设计基于flask应急救援调度系统django

此系统设计主要采用的是python语言来进行开发,采用flask框架技术,框架分为三层,分别是控制层Controller,业务处理层Service,持久层dao,能够采用多层次管理开发,对于各个模块设计制作有一定的安全…

动态规划题目练习

基础知识: 动态规划背包问题-CSDN博客 动态规划基础概念-CSDN博客 题目练习: 题目1:过河卒 题目描述 棋盘上 A 点有一个过河卒,需要走到目标 B 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 C 点有一个对方的马…

WebGIS管线在线编辑器(电力、水力、燃气、热力、热能管线)

随着GIS等信息技术的发展,地下管线管理也从二维平面向三维立体管理迈进。传统管线信息管理系统将管线及其附属设施抽象成二维平面内的点、要素,并使用各类点符号、不同颜色线段进行表达。虽能一定程度上满足城市智慧运行的需要,但不能很直观的…

【Linux】文件描述符 - fd

文章目录 1. open 接口介绍1.1 代码演示1.2 open 函数返回值 2. 文件描述符 fd2.1 0 / 1 / 22.2 文件描述符的分配规则 3. 重定向3.1 dup2 系统调用函数 4. FILE 与 缓冲区 1. open 接口介绍 使用 man open 指令查看手册&#xff1a; #include <sys/types.h> #include …

02. Java 中的关键字、标识符、运算符、分隔符和注释

关键字 Java 的关键字(keyword、保留字)是 Java 语言中具有特殊含义的单词&#xff0c;它们被保留供 Java 自身使用&#xff0c;不能被用作标识符。例如 public、class、void、int 等都是关键字。 关键字在 Java 语法中起着重要的作用&#xff0c;它们定义了编程的结构、控制…

Python 深度学习第二版(GPT 重译)(一)

前言 序言 如果你拿起这本书&#xff0c;你可能已经意识到深度学习在最近对人工智能领域所代表的非凡进步。我们从几乎无法使用的计算机视觉和自然语言处理发展到了在你每天使用的产品中大规模部署的高性能系统。这一突然进步的后果几乎影响到了每一个行业。我们已经将深度学…

【数据结构与算法】(13):冒泡排序和快速排序

&#x1f921;博客主页&#xff1a;Code_文晓 &#x1f970;本文专栏&#xff1a;数据结构与算法 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多数据结构与算法点击专栏链接查看&…

揭秘2024云渲染平台优惠陷阱!有些看似划算实则很坑

近年来&#xff0c;随着云渲染技术的飞速发展&#xff0c;越来越多的人开始关注并使用云渲染平台。然而其中隐藏着一些消费陷阱&#xff0c;需要我们谨慎小心。有时候一些平台看似优惠&#xff0c;实际上可能是一个深不见底的坑。 今天小编就来对比分析2024年市面上主流的五款云…

MT管理器 使用手册

MT管理器 论坛&#xff1a;https://bbs.binmt.cc/ 使用技巧系列教程&#xff1a;https://www.52pojie.cn/thread-1259872-1-1.html MT管理器 使用手册 &#xff1a;https://mt2.cn/guide/&#xff1a;https://www.bookstack.cn/read/mt-manual/80b8084f6be128c0.md&#xff…

外包干了5天,技术退步明显。。。。

说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&a…

exporter方式监控达梦数据库

蓝鲸监控 随着国产化和信创的深入&#xff0c;开始普遍使用国产化数据库–如达梦数据库&#xff0c;蓝鲸平台默认没有对其进行监控&#xff0c;但是平台了提供监控告警的能力。比如脚本采集&#xff0c;脚本的是一种灵活和快速的监控采集方式&#xff0c;不同层的监控对象都可…

SqlServer数据库复习总结资料

基于课堂上学到的以及书上的看到的&#xff0c;总结出的数据库复习资料 一、数据库概述 基本概念 1.数据 数据&#xff08;Data&#xff09;是事物的符号表示&#xff0c;可以是声音、图像、文字、数字&#xff0c;也可以是计算机代码。 2.数据库 数据库&#xff08;DataBase…

pytorch之诗词生成6--eval

先上代码&#xff1a; import tensorflow as tf from dataset import tokenizer import settings import utils# 加载训练好的模型 model tf.keras.models.load_model(r"E:\best_model.h5") # 随机生成一首诗 print(utils.generate_random_poetry(tokenizer, model)…

WebXR实践——利用aframe框架浏览器展示全景图片

一、效果 话不多说&#xff0c;先上效果 二、代码 index.html <!DOCTYPE html> <html><head><meta charset"utf-8"><title>360&deg; Image</title><meta name"description" content"360&deg; Imag…

JavaSE:数据类型与变量

目录 一、前言 二、数据类型与变量 &#xff08;一&#xff09;字面常量 &#xff08;二&#xff09;数据类型 &#xff08;三&#xff09;变量 1.变量概念 2.语法格式 3.整型变量 3.1整型变量 3.2长整型变量 3.3短整型变量 3.4字节型变量 4.浮点型变量 4.1双精…

REDHAWK——连接(续)

文章目录 前言一、突发 IO1、数据传输①、输入②、输出 2、突发信号相关信息 (SRI)3、多输出端口4、使用复数数据①、在 C 中转换复数数据 5、时间戳6、端口统计①、C 二、消息传递1、消息生产者①、创建一个消息生产者②、发送消息 2、消息消费者①、创建消息消费者②、注册接…

01mysql

登陆mysql 默认数据库 进入&#xff0c;展示&#xff0c;删除 &#xff0c;查看当前正使用的库 select version()查看版本 查看表结构desc 查询 not in不会忽略空 in会自动忽略 like模糊查询 %o%中间带o的 _A%第二个字母是A的 查名字是下划线的 %\_% 排序 order …