【python】进阶--->并发编程之线程(二)

一、线程的生命周期

新建 : 创建线程经过初始化,进入就绪状态
就绪 : 等待操作系统调度,调度后进入运行状态运行
阻塞 : 暂停运行,解除阻塞后进入就绪等待重新调度
消亡 : 线程执行完毕或者异常终止

可能有3种情况从运行到阻塞 :

  • 同步 : 线程中获取同步锁,但是资源已经被其他线程锁定,进入locked状态,直到该资源可以获取
  • 睡眠 : 线程运行sleep或者join方法后,进入sleep状态.区别在于sleep是阻塞自己等待一定的时间,join是阻塞其他线程等待调用join的线程执行完毕.
  • 等待 : 线程中执行wait方法,等待其他线程通知notify.

线程共享全局变量

在这里插入图片描述

import threading, timenum = 5
# num = [1, 2, 3, 4]def test1():global num# num += 1# num.append(5)for i in range(10):time.sleep(1)num += 1print('test1---', num)def test2():global numfor i in range(10):time.sleep(1)num += 1print('test2---', num)if __name__ == '__main__':t1 = threading.Thread(target=test1)t1.start()t2 = threading.Thread(target=test2)t2.start()

在一个进程内所有的线程共享全局变量,很方便多个线程键共享数据
缺点就是,线程对全局变量随机修改可能在成多线程之间全局变量的混乱.

线程的数量

import threading
import timedef test1():for i in range(3):print('test1---%s' % i)time.sleep(1)def test2():for i in range(3):print('test2---%s' % i)time.sleep(1)if __name__ == '__main__':print('开始')# len(threading.enumerate())print('t1创建之前,线程的数量:', len(threading.enumerate()))t1 = threading.Thread(target=test1)print('t1创建之后,t2创建前,线程的数量:', len(threading.enumerate()))t2 = threading.Thread(target=test2)print('t2创建后,线程的数量:', len(threading.enumerate()))# 调用start方法的时候,才会真正创建一条线程t1.start()print('t1启动之后,t2启动前,线程的数量:', len(threading.enumerate()))t2.start()print('t2启动后,线程的数量:', len(threading.enumerate()))

线程的执行顺序

import threading
import timeclass MyThread(threading.Thread):def run(self):for i in range(3):time.sleep(1)print('这是线程%s在进行第%s循环' % (self.name, i))if __name__ == '__main__':for i in range(5):t = MyThread()t.start()# 多条线程执行的顺序是不确定的,当执行到sleep语句时
# 线程将被阻塞,sleep结束之后,线程进入就绪状态,等待调度
# 线程调度是操作系统自行选择的.
# 所以只能保证每个线程都完整的执行了,但是启动顺序和函数执行的顺序是不能确定的

主线程和子线程

import time, threadingdef test1():for i in range(10):time.sleep(1)print('test1----')def test2():for i in range(5):time.sleep(1)print('test2----')if __name__ == '__main__':print('主线程开始运行')t = threading.Thread(target=test1)t2 = threading.Thread(target=test2)t.setDaemon(True)  # 设置为守护线程t.start()t.join()t2.start()print('主线程结束')

二、同步和互斥

同时运行的多个任务可能:
都需要访问/使用同一种资源
多个任务之间有依赖关系,某个任务的运行依赖于另一个任务

互斥 : 散布在不同任务之间的若干个程序片段,当某个任务运行一个程序片段是,其他任务就不能运行他们之中的任何一个,只能等待该任务运行完这个程序片段之后才可以运行.比如说:一个公共资源同一时刻只能被一个进程或线程使用,多个进程或线程不能同时使用公共资源.

同步 : 散布在不同任务之间的若干个程序片段,他们的运行必须严格按照规定的某种先后顺序来运行,这种先后顺序必须依赖于要完成特定的任务.

三、互斥锁

当多个线程几乎同时修改某一个共享数据时,需要进行同步控制.
线程同步能够保证线程安全访问资源,最简单的机制就是引入互斥锁.为资源引入一个状态:锁定/非锁定
某个线程要更改数据时,先将数据进行锁定,此时资源的状态为”锁定”,其他线程不能更改.
等待该线程执行完,将资源的状态修改为”非锁定”,其他的线程才能去再次锁定该线程.
threading模块中的Lock()

创建锁

mutex = threading.Lock()

锁定

mutex.acquire()

释放

mutex.release()

如果这个锁之前是没有上锁的,那么acquire就不会阻塞.如果在调用acquire对这个锁上锁之前已经被其他线程上锁了,那么就会阻塞,直到锁被释放为止.

死锁

死锁 : 两个或者两个以上的进程在执行的过程中,因为抢夺资源而造成一种互相等待的现象.如果没有外力作用,将无法进行下去.
避免死锁 : 银行家算法,添加超时时间

import threading, timenum = 0def test1():global numfor i in range(100):mutex.acquire()num += 1mutex.release()print('---test1---', num)def test2():global numfor i in range(100):mutex.acquire()num += 1mutex.release()print('---test2---', num)if __name__ == '__main__':mutex = threading.Lock()mutex1 = threading.Lock()t1 = threading.Thread(target=test1)t2 = threading.Thread(target=test2)t1.start()t2.start()print('主线程:', num)

四、银行家算法

银行家算法 : 操作系统看做银行家,操作系统管理的资源相当于银行家的资金,进程向操作系统请求分配资源相当于用户向银行贷款.银行规定 :
1.当顾客对资金的最大需求量不超过银行现有的资金时才接纳顾客.
2.顾客可以贷款,但是贷款总数不能超过最大需求量.
3.当银行现有的资金不能满足顾客现需的贷款数额时,对顾客的贷款可推迟支付,但是总能让在顾客的有限时间里得到贷款.
4.当顾客得到所需的全部资金后,一定要在有限的时间里归还所有资金.

五、多线程案例

生产者消费者模式

生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题.
生产者和消费者彼此之间不直接通信,而是通过阻塞队列来进行通信,所有生产者生产完数据不用等待消费者处理直接放到阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列获取.这样就解决了因为生产生产速度慢或者消费者消费处理能力造成的资源浪费.

import threading, time, random, multiprocessingclass Producer(threading.Thread):def __init__(self, name, queue):threading.Thread.__init__(self, name=name)# super().父类方法()# 父类名.父类方法(self)self.data = queuedef run(self):for i in range(5):print('%s正在生产%s' % (self.getName(), i))self.data.put(i)time.sleep(random.random())print('%s生产结束' % self.getName())class Consumer(threading.Thread):def __init__(self, name, queue):threading.Thread.__init__(self, name=name)self.data = queuedef run(self):for i in range(5):value = self.data.get()print('%s正在消费%s' % (self.name, value))time.sleep(random.random())print('%s消费结束' % self.name)if __name__ == '__main__':queue = multiprocessing.Queue()p = Producer('生产者', queue)c = Consumer('消费者', queue)p.start()c.start()print('线程结束')

关于Python线程的所有介绍今天就到这里啦,后续我会为大家介绍协程的相关知识哦~
关注我,带你领略Python的风采~😍😍😍

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

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

相关文章

车辆跟踪及测距

车辆跟踪及测距是一种现代化的技术手段,通过使用各种传感器和技术设备,能够实现车辆的实时监控和测距。这些技术手段包括GPS全球定位系统、雷达、激光等,它们可以帮助我们更好地了解车辆的位置和行驶情况。在本文中,我们将从以下几…

LeetCode - 460 LFU缓存(Java JS Python)

题目来源 460. LFU 缓存 - 力扣(LeetCode) 题目描述 请你为 最不经常使用(LFU)缓存算法设计并实现数据结构。 实现 LFUCache 类: LFUCache(int capacity) - 用数据结构的容量 capacity 初始化对象int get(int key)…

【迁移学习论文四】Multi-Adversarial Domain Adaptation论文原理及复现工作

Multi-Adversarial Domain Adaptation 多对抗域适应 前言 好久没有更新了,所以这周开始记录下来,也好督促自己。记录本人预备研究生阶段相关迁移学习论文的原理阐述以及复现工作。 问题 跨域混淆或错误对齐 文章介绍 这篇文章于2018年发表在AAAI&…

手把手教你使用Cypress进行端到端测试

一、引言 Cypress是一个流行的端到端测试框架,它提供了一个全面的解决方案,可以测试任何在浏览器中运行的内容。不论你是想为一个小型项目添加测试,还是在大型企业级应用中进行端到端测试,Cypress都是一个不错的选择。本文将会手…

智能优化算法应用:基于阿基米德优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于阿基米德优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于阿基米德优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.阿基米德优化算法4.实验参数设定…

国家开放大学 河南开放大学形成性考核 平时作业 统一参考资料

试卷代号:1258 房屋建筑混凝土结构设计 参考试题 一、单项选择题(每小题2分,共计40分) 1.( )是将框架结构中的部分跨间布置剪力墙或把剪力墙结构的部分剪力墙抽掉改为框架承重。 A.梁板结构体系 B.框…

评价机器学习模型的指标

为了衡量一个机器学习模型的好坏,需要给定一个测试集,用模型对测试集中的每一个样本进行预测,并根据预测结果计算评价分数。 对于分类问题,常见的评价标准有准确率、精确率、召回率和F值等。给定测试集 𝒯 {(&#x1…

一款电压检测LVD

一、基本概述 The TX61C series devices are a set of three terminal low power voltage detectors implemented in CMOS technology. Each voltage detector in the series detects a particular fixed voltage ranging from 0.9V to 5.0V. The voltage detectors consist…

git缓存区、本地仓库、远程仓库的同步问题(初始化库无法pull和push)

git新建库与本地库同步 gitee使用教程,git的下载与安装接不在叙述了。 新建远程仓库 新建远程仓库必须要使用仓库提供的api,也就是仓库门户网站,例如gitee,github,gitlab等。在上图中使用gitee网址中新建了一个test仓…

回归预测 | MATLAB实现NGO-SCN北方苍鹰算法优化随机配置网络的数据回归预测 (多指标,多图)

回归预测 | MATLAB实现NGO-SCN北方苍鹰算法优化随机配置网络的数据回归预测 (多指标,多图) 目录 回归预测 | MATLAB实现NGO-SCN北方苍鹰算法优化随机配置网络的数据回归预测 (多指标,多图)效果一览基本介绍…

HarmonyOS(十五)——状态管理之@Prop装饰器(父子单向同步)

上一篇文章我们认识了状态管理的State装饰器(组件内状态),接下来我们学习另外一个状态管理装饰器Prop装饰器。 Prop装饰的变量可以和父组件建立单向的同步关系。Prop装饰的变量是可变的,但是变化不会同步回其父组件。 说明&#…

10分钟微调专属于自己的大模型

本文主要介绍使用魔搭社区轻量级训练推理工具SWIFT,进行大模型自我认知微调,帮助初阶炼丹师快速微调出专属于自己的大模型。 SWIFT(Scalable lightWeight Infrastructure for Fine-Tuning)是魔搭ModelScope开源社区推出的一套完整…

泰坦陨落2找不到msvcr120文件的修复方法,分享多种解决方法

在玩泰坦陨落2这款游戏时,有些玩家可能会遇到找不到msvcr120.dll文件的问题。这个问题可能是由于游戏缺少必要的运行库导致的。下面我将分享一些解决这个问题的方法,希望对大家有所帮助。 一、问题分析 msvcr120.dll是Microsoft Visual C Redistributab…

MATLAB - 使用 MPC Designer 线性化 Simulink 模型

系列文章目录 前言 本主题介绍如何使用 MPC Designer 对 Simulink 模型进行线性化。为此,请从包含 MPC 控制器块的 Simulink 模型打开该应用程序。本例中使用 CSTR_ClosedLoop 模型。 open_system(CSTR_ClosedLoop) 在模型窗口中,双击 MPC 控制器模块。…

Vue中英文翻译小结

背景:时局艰难,后端开发被强制写了vue,这不有个需求是中英文翻译,特此记录下,该怎么个翻译法子。 先引入全局的路由国际化文件,zh.js 和 en.js 1.关于插值表达Button里面 {{ $t(reinsop.common.back) }} …

LazyIDA源码阅读

LazyIDA是一款IDA插件,项目地址GitHub - L4ys/LazyIDA: Make your IDA Lazy! 外部引用 from __future__ import division from __future__ import print_function from struct import unpack import idaapi import idautils import idcfrom PyQt5.Qt import QAppli…

vue中的事件修饰符、表单双向数据绑定和计算属性

目录 一、事件修饰符 二、表单双向数据绑定 模拟双向数据绑定(双向数据绑定底层原理) 三、计算属性 计算属性和methods方法区别? 计算属性和watch区别? 一、事件修饰符 stop 阻止事件冒泡 prevent 阻止事件默认行为 ca…

Linux线程——互斥锁

概念 互斥量(mutex)从本质上来说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁。对互斥量进行加锁后,任何其他试图再次对互斥量加锁的线程将会被阻塞直到当前线程释放该互斥锁。 如果释放…

【HCIP学习记录】OSPF之DD报文

1.OSPF报文格式 24字节 字段长度含义Version1字节版本,OSPF的版本号。对于OSPFv2来说,其值为2。Type1字节类型,OSPF报文的类型,有下面几种类型: 1:Hello报文;● 2:DD报文&#xff1…

美国联邦机动车安全标准-FMVSS

FMVSS标准介绍: FMVSS是美国《联邦机动车安全标准》,由美国运输部下属的国家公路交通安全管理局(简称NHTSA)具体负责制定并实施。是美国联邦政府针对机动车制定的安全标准,旨在提高机动车的安全性能,减少交通事故中的人员伤亡。F…