并发编程 # 3
文章目录
- 一、进程和线程的比较
- 二、GIL全局解释器锁
- 1.引入
- 2.Python解释器的种类
- 结论:在CPython解释其中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势。
- 得出结论:GIL锁就是保证在同一时刻只有一个线程执行,所有的线程必须拿到GIL锁才有执行权限
- 以下几个问题需要理解记忆
- 3.互斥锁
- 4.线程队列(线程里使用队列)
- 1.为什么线程中还有使用队列?
- 2.线程队列:
- 5.进程池和线程池的使用
- 6.多线程爬取网页
- 7.协程理论
- 协程实现高并发
一、进程和线程的比较
1.进程的开销比线程开销大很多
2.进程之间的数据是隔离开的,但是,线程之间的数据不隔离
3.多个进程之间的线程数据不共享
二、GIL全局解释器锁
1.引入
首先要明白,GIL并不是Python的一个特性,其实在我们通常所称呼的Python解释器,其实是CPython解释器,因为大部分Python程序都是基于该解释器执行的,当然还有JPython解释器(基于Java编写的),而这个GIL则是CPython解释器的特性,而不是Python的特性。
GIL全程:Global Interpreter Lock,官方解释:
In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)
2.Python解释器的种类
CPython
IPython
PyPy
JPython
IronPython
当前市场使用最多的解释器就是CPython解释器
GIL全局解释器锁是存在于CPython中
结论:在CPython解释其中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势。
比如:现在起一个线程,来回收垃圾数据,回收a=1这个变量,另外一个线程也要使用这个变量a,当垃圾回收线程还没没有把变量a回收完毕,另一个线程就来抢夺这个变量a使用。
怎么避免的这个问题,那就是在Python这门语言设计之处,就直接在解释器上添加了一把锁,这把锁就是为了让统一时刻只有一个线程在执行,言外之意就是哪个线程想执行,就必须先拿到这把锁(GIL), 只有等到这个线程把GIL锁释放掉,别的线程才能拿到,然后具备了执行权限.
得出结论:GIL锁就是保证在同一时刻只有一个线程执行,所有的线程必须拿到GIL锁才有执行权限
以下几个问题需要理解记忆
1.Python有GIL的原因,同一个进程下多个线程实际上同一时刻只有一个线程在执行
2.只有在Python上开进程用的多,其他语言一般不多开进程,只开多线程就够了
3.CPython解释器开多线程不能利用多核优势,只有开多进程才能利用多核优势,其他语言不存在这个问题
4.八核CPU电脑,要充分利用起这8个核,至少起8个线程,8条线程全是计算,计算机CPU使用率是100%
5.如果不存在GIL锁,一个进程下,开启8个线程,他就能够充分利用CPU资源,跑满CPU
6.CPython解释器中好多代码,模块都是基于GIL锁机制写起来的,改不了,我们不能用8核,只能用一个核,开启多进程,每个进程下开启的线程,可以被多个CPU调度执行
7.CPython解释器:io密集型使用多线程,计算密集型使用多进程
io密集型,遇到io操作会切换cpu,假设你开了8个线程,8个线程都有io操作—》io操作不消耗cpu—》一段时间内看上去,其实8个线程都执行了, 选多线程好一些
计算密集型,消耗cpu,如果开了8个线程,第一个线程会一直占着cpu,而不会调度到其他线程执行,其他7个线程根本没执行,所以我们开8个进程,每个进程有一个线程,8个进程下的线程会被8个cpu执行,从而效率高
计算密集型选多进程好一些,在其他语言中,都是选择多线程,而不选择多进程.
3.互斥锁
在多线程的情况下,同时执行一个数据,就会发生数据错乱问题
n = 10
from threading import Lock
import time
def task(lock):lock.acquire()global ntemp = ntime.sleep(0.5)n = temp - 1lock.release()"""拿时间换空间,空间换时间 时间复杂度"""
from threading import Threadif __name__ == '__main__':tt = []lock=Lock()for i in range(10):t = Thread(target=task, args=(lock, ))t.start()tt.append(t)for j in tt:j.join()print("主", n)
面试题:既然有了GIL锁,为什么还要互斥锁? (多线程下)
比如:我起了2个线程,来执行a=a+1,a一开始是0
1.第一个线程来了,拿到a=0,开始执行a=a+1,这个时候结果a就是1了
2.第一个线程得到的结果1还没有赋值回去给a,这个时候,第二个线程来了,拿到的a是0,继续执行
a=a+1结果还是1
3.加了互斥锁,就能够解决多线程下操作同一个数据,发生错乱的问题
4.线程队列(线程里使用队列)
1.为什么线程中还有使用队列?
同一个进程下多个线程数据是共享的
为什么先同一个进程下还会去使用队列呢
因为队列是:管道+锁
所以用队列还是为了保证数据的安全
2.线程队列:
1.先进后出
2.后进先出
3.优先级的队列
from multiprocessing import Queue"""线程队列"""
import queue
queue.Queue()# queue.Queue 的缺点是它的实现涉及到多个锁和条件变量,因此可能会影响性能和内存效率。
import queueq=queue.Queue() # 无限大、
q.put('first')
q.put('second')
q.put('third')
q.put('third')
q.put('third')
q.put('third')
q.put('third')print(q.get())
print(q.get())
print(q.get())## 后进先出
import queue# Lifo:last in first out
q=queue.LifoQueue()
q.put('first')
q.put('second')
q.put('third')print(q.get())
print(q.get())
print(q.get())## 优先级队列
import queueq=queue.PriorityQueue()
#put进入一个元组,元组的第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小优先级越高
q.put((20,'a'))
q.put((10,'b'))
q.put((30,'c'))print(q.get())
print(q.get())
print(q.get())
'''
结果(数字越小优先级越高,优先级高的优先出队):
(10, 'b')
(20, 'a')
(30, 'c')
'''
5.进程池和线程池的使用
池:池子、容器类型,可以盛放多个元素
进程池:提前定义好一个池子,然后,往这个池子里添加进程,以后只需要往这个进程池里面丢进任务就行,然后有了这个进程池里面的任意一个进程来执行任务
线程池:提前定义好一个池子,然后,往这个池子里面添加下城,以后,只需要往这个线程池里面添加任务就行,然后,有了这个线程池里面的任意一个线程来执行任务
进程池和线程池有什么好处呢?
def task(n, m):return n+mdef task1():return {'username':'kevin', 'password':123}
"""开进程池"""
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutordef callback(res):print(res) # Future at 0x1ed5a5e5610 state=finished returned int>print(res.result()) # 3def callback1(res):print(res) # Future at 0x1ed5a5e5610 state=finished returned int>print(res.result()) # {'username': 'kevin', 'password': 123}print(res.result().get('username'))
if __name__ == '__main__':pool=ProcessPoolExecutor(3) # 定义一个进程池,里面有3个进程## 2. 往池子里面丢任务pool.submit(task, m=1, n=2).add_done_callback(callback)pool.submit(task1).add_done_callback(callback1)pool.shutdown() # join + closeprint(123)
6.多线程爬取网页
import requestsdef get_page(url):res=requests.get(url)name=url.rsplit('/')[-1]+'.html'return {'name':name,'text':res.content}def call_back(fut):print(fut.result()['name'])with open(fut.result()['name'],'wb') as f:f.write(fut.result()['text'])if __name__ == '__main__':pool=ThreadPoolExecutor(2)urls=['http://www.baidu.com','http://www.cnblogs.com','http://www.taobao.com']for url in urls:pool.submit(get_page,url).add_done_callback(call_back)
7.协程理论
进程资源分配
线程执行的最小单位
协程"""他是程序员自己意淫出来的,它不是在操作系统中实际存在的"""# 协程就是单线程下的并发
并发:切换+保存状态
# 以前的并发的切换其实是进程或者线程在切换既然是单线程下了,你说节省资源不
协程是最节省资源的,进程是最消耗资源的,其次是线程"""问题来了:怎么监测有没有遇到IO?"""
# 这里的切换是程序员级别的切换,我们自己切,不是操作系统切的
本上上就是最大限度的利用CPU资源
pip install geventimport gevent
协程实现高并发
服务端:
from gevent import monkey;monkey.patch_all()
import gevent
from socket import socket
# from multiprocessing import Process
from threading import Threaddef talk(conn):while True:try:data = conn.recv(1024)if len(data) == 0: breakprint(data)conn.send(data.upper())except Exception as e:print(e)conn.close()def server(ip, port):server = socket()server.bind((ip, port))server.listen(5)while True:conn, addr = server.accept()# t=Process(target=talk,args=(conn,))# t=Thread(target=talk,args=(conn,))# t.start()gevent.spawn(talk, conn)if __name__ == '__main__':g1 = gevent.spawn(server, '127.0.0.1', 8080)g1.join()客户端:import socket
from threading import current_thread, Threaddef socket_client():cli = socket.socket()cli.connect(('127.0.0.1', 8080))while True:ss = '%s say hello' % current_thread().getName()cli.send(ss.encode('utf-8'))data = cli.recv(1024)print(data)for i in range(5000):t = Thread(target=socket_client)t.start()相关文章:
并发编程 # 3
文章目录 一、进程和线程的比较二、GIL全局解释器锁1.引入2.Python解释器的种类结论:在CPython解释其中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势。得出结论:GIL锁就是保证在同一时刻只…...
ESP32C3 LuatOS TM1650①驱动测试
合宙TM1650驱动资料 TM1650.lua源码 引脚连接 TM1650ESP32C3SCLGPIO5SDAGPIO4 下载TM1650.lua源码,并以文件形式保存在项目文件夹中 驱动测试源码 --注意:因使用了sys.wait()所有api需要在协程中使用 -- 用法实例 PROJECT "ESP32C3_TM1650" VERSION …...
TCP为什么需要三次握手和四次挥手?
一、三次握手 三次握手(Three-way Handshake)其实就是指建立一个TCP连接时,需要客户端和服务器总共发送3个包 主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备 过程如下ÿ…...
【C++】一些C++11特性
C特性 1. 列表初始化1.1 {}初始化1.2 initializer_list 2. 声明2.1 auto2.2 typeid2.3 decltype2.4 nullptr 3. STL3.1 新容器3.2 新接口 4. 右值引用5. 移动构造与移动赋值6. lambda表达式7. 可变参数模板8. 包装器9. bind 1. 列表初始化 1.1 {}初始化 C11支持所有内置类型和…...
leetcode 647. 回文子串、516. 最长回文子序列
647. 回文子串 给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串,即使是由相同的字符组成&#…...
Vue Router 刷新当前页面
Vue项目, 在实际工作中, 有些时候需要在 加载完某些数据之后对当前页面进行刷新, 以期 onMounted 等生命周期函数, 或者 数据重新加载. 总之是期望页面可以重新加载一次. 目前总结有三种途径可实现以上需求: 一, reload 直接刷新页面 window.location.reload(); $router.go(…...
lstm 回归实战、 分类demo
预备知识 lstm 参数 输入、输出格式 nn.LSTM(input_dim,hidden_dim,num_layers); imput_dim 特征数 input:(样本数、seq, features_num) h0,c0 (num_layers,seq, hidden_num) output: (样本数、seq, hidden_dim) 再加一个全连接层,将 outpu…...
实践DDD模拟电商系统总结
目录 一、事件风暴 二、系统用例 三、领域上下文 四、架构设计 (一)六边形架构 (二)系统分层 五、系统实现 (一)项目结构 (二)提交订单功能实现 (三࿰…...
`SQL`编写判断是否为工作日函数编写
SQL编写判断是否为工作日函数编写 最近的自己在写一些功能,遇到了对于工作日的判断,我就看了看sql,来吧!~(最近就是好疲惫) 我们一起看看(针对ORACLE) 1.声明: CREATE OR REPLACE PACKAGE GZYW_2109_1214.PKG_FUN_GETDAY_HDAY AS /** * 通过节假日代码获取指定的日期[查找基…...
零信任身份管理平台,构建下一代网络安全体系
随着数字化时代的到来,网络安全已成为企业和组织面临的一项重要挑战。传统的网络安全方法已经无法满足不断演变的威胁和技术环境。近期,中国信息通信研究院(简称“中国信通院”)发布了《零信任发展研究报告( 2023 年&a…...
《数据结构、算法与应用C++语言描述》使用C++语言实现链表队列
《数据结构、算法与应用C语言描述》使用C语言实现链表队列 定义 队列的定义 队列(queue)是一个线性表,其插入和删除操作分别在表的不同端进行。插入元素的那一端称为队尾(back或rear),删除元素的那一端称…...
RT-Thread学习笔记(四):RT-Thread Studio工具使用
RT-Thread Studio工具使用 官网详细资料实用操作1. 查看 RT-Thread RTOS API 文档2.打开已创建的工程3.添加头文件路径4. 如何设置生成hex文件5.新建工程 官网详细资料 RT-Thread Studio 用户手册 实用操作 1. 查看 RT-Thread RTOS API 文档 2.打开已创建的工程 如果打开项目…...
【计算机网络笔记】OSI参考模型中端-端层(传输层、会话层、表示层、应用层)功能介绍
系列文章目录 什么是计算机网络? 什么是网络协议? 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能(1)——速率、带宽、延迟 计算机网络性能(2)…...
RabbitMQ高级知识点
以下是一些 RabbitMQ 的高级知识点: 1. Exchange: RabbitMQ 中的 Exchange 是消息路由器,用来接收消息并且转发到对应的 Queue 中。Exchange 有四种类型:Direct Exchange、Fanout Exchange、Topic Exchange 和 Headers Exchange。…...
Node直接执行ts文件
Node直接执行ts文件 1、常规流程 node 执行 【ts 文件】 流程: 1、编写ts代码 2、编译成js代码 [命令如 :tsc xx.ts] 3、执行js代码 [node xx.js]2、直接执行 想要直接执行 ts 文件,需要安装如下依赖工具。 执行如下命令: # 安装…...
log4j的级别的说明
一 log4j的级别 1.1 级别类型 TRACE 》DEBUG 》 INFO 》 WARN 》 ERROR 》 FATAL 级别高低顺序为: trace级别最低 ,Fatal级别最高。由左到右,从低到高 1.2 包含范围 原则: 本级别包含本级别以及大于本级别的内容,…...
头脑风暴之约瑟夫环问题
一 问题的引入 约瑟夫问题的源头完全可以命名为“自杀游戏”。本着和谐友爱和追求本质的目的,可以把问题描述如下: 现有n个人围成一桌坐下,编号从1到n,从编号为1的人开始报数。报数也从1开始,报到m人离席,…...
【四:Spring整合Junit】
目录 相同点不同点1、导入依赖增加2、编写的位置不同。。路径一定要与实现类一致 相同点 前面都一样和Spring整合mybatis(基于注解形式)一样Spring整合Mybatis 不同点 1、导入依赖增加 <!-- 单元测试 --><dependency><groupId>junit&…...
openHarmony UI开发
常用组件和布局方式 组件 ArkUI有丰富的内置组件,包括文本、按钮、图片、进度条、输入框、单选框、多选框等。和布局一样,我们也可以将基础组件组合起来,形成自定义组件。 按钮: Button(Ok, { type: ButtonType.Normal, stateEf…...
Qt 目录操作(QDir 类)及展示系统文件实战 QFilelnfo 类介绍和获取文件属性项目实战
一、目录操作(QDir 类) QDir 类提供访问系统目录结构 QDir 类提供对目录结构及其内容的访问。QDir 用于操作路径名、访问有关路径和文件的信息以及操作底层文件系统。它还可以用于访问 Qt 的资源系统 Qt 使用“/”作为通用目录分隔符,与“/”在 URL 中用作路径分…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果实现跳一跳小游戏
下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...
