一、local
在多个线程之间使用threading.local对象,可以实现多个线程之间的数据隔离 import time
import random
from threading import Thread,local loc = local() def func1():
global loc
print(loc.name,loc.age) def func2(name,age):
global loc
loc.name = name
loc.age = age
time.sleep(random.uniform(0,2))
func1() Thread(target=func2,args=('明哥',19)).start()
Thread(target=func2,args=('小弟',17)).start() 结果:
小弟 17
明哥 19 解释:
在平时的线程中,应该每次打印的结果应该都是最后进来的线程的数据,即第一次的数据会被第二次的数据覆盖,
但是使用了local对象,可以实现线程的数据隔离,因此打印的两次结果都不一样。 原理:
local对象会创建一个大字典,字典的键是线程的id,值也是一个字典,存储数据,例如: {
线程id1:{'name':'明哥',age:19}
线程id2:{'name':'小弟',age:17}
...
} 二、
1、阻塞IO(blocking IO)

当用户进程调用了recv/recvfrom这些系统调用时,操作系统就开始了IO的第一个阶段:准备数据。因为很多时候数据一开始还没有到达(比如,还没有收到一个完整的UDP包),这个时候操作系统就要等待足够的数据到来。
而在用户进程这边,整个进程会被阻塞。操作系统一直等到数据准备好了,它就会将数据拷贝到用户内存,然后返回结果,用户进程才解除block的状态,重新运行起来。
所以,blocking IO的特点就是在IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被block了。 几乎所有的程序员第一次接触到的网络编程都是从listen()、send()、recv() 等接口开始的,使用这些接口可以很方便的构建服务器/客户机的模型。然而大部分的socket接口都是阻塞型的。
阻塞型接口是指系统调用(一般是IO接口)不返回调用结果并让当前线程一直阻塞,只有当该系统调用获得结果或者超时出错时才返回。
实际上,除非特别指定,几乎所有的IO接口 ( 包括socket接口 ) 都是阻塞型的。这给网络编程带来了一个很大的问题,如在调用recv(1024)的同时,线程将被阻塞,在此期间,线程将无法执行任何运算或响应任何的网络请求。 解决方案:
在服务器端使用多线程(或多进程)。多线程(或多进程)的目的是让每个连接都拥有独立的线程(或进程),这样任何一个连接的阻塞都不会影响其他的连接。 该方案的问题是:
开启多进程或都线程的方式,在遇到要同时响应成百上千路的连接请求,则无论多线程还是多进程都会严重占据系统资源,降低系统对外界响应效率,而且线程与进程本身也更容易进入假死状态。 改进方案:
很多程序员可能会考虑使用“线程池”或“连接池”。“线程池”旨在减少创建和销毁线程的频率,其维持一定合理数量的线程,并让空闲的线程重新承担新的执行任务。“连接池”维持连接的缓存池,尽量重用已有的连接、减少创建和关闭连接的频率。这两种技术都可以很好的降低系统开销,都被广泛应用很多大型系统,如websphere、tomcat和各种数据库等。 改进后方案其实也存在着问题:
“线程池”和“连接池”技术也只是在一定程度上缓解了频繁调用IO接口带来的资源占用。而且,所谓“池”始终有其上限,当请求大大超过上限时,“池”构成的系统对外界的响应并不比没有池的时候效果好多少。所以使用“池”必须考虑其面临的响应规模,并根据响应规模调整“池”的大小。 对应上例中的所面临的可能同时出现的上千甚至上万次的客户端请求,“线程池”或“连接池”或许可以缓解部分压力,但是不能解决所有问题。总之,多线程模型可以方便高效的解决小规模的服务请求,但面对大规模的服务请求,多线程模型也会遇到瓶颈,可以用非阻塞接口来尝试解决这个问题。 2、非阻塞IO

非阻塞IO操作一些时,如果操作系统中的数据还没有准备好,它也不会出现阻塞,而是立刻返回一个error。用户进程可以判断这个返回值是否是error,如果是它就知道数据还没有准备好,于是用户就可以在下次询问前的时间内做其他事情。如果数据准备好了,且用户再次进行询问时,那么数据就可以拷贝到用户内存(这一阶段仍然是阻塞的),然后返回。
其实在非阻塞式IO中,用户进程其实是需要不断的主动询问操作系统数据是否准备好了。 例如:
Server端:
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.setblocking(False) # 设置当前的server为一个非阻塞IO模型
sk.listen() conn_lst = []
del_lst = [] while True:
try:
conn,addr = sk.accept()
conn_lst.append(conn)
except BlockingIOError:
for conn in conn_lst:
try:
conn.send(b'hello')
print(conn.recv(1024))
except (NameError,BlockingIOError):pass
except ConnectionResetError:
conn.close()
del_lst.append(conn)
for del_conn in del_lst:
conn_lst.remove(del_conn)
del_lst.clear() Client端:
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',8080)) while 1:
print(sk.recv(1024))
sk.send(b'heiheihei') 这样就可以实现非阻塞IO下基于TCP的并发socket,
但是这样的非阻塞IO大量的占用了CPU导致了资源的浪费并且给CPU造成了很大的负担 3、多路复用IO

当用户进程调用了select,那么整个进程会被block,同时,操作系统会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从操作系统拷贝到用户进程。 多路复用IO与阻塞IO:
多路复用IO需要使用两次系统调用,而阻塞IO只调用了一个系统调用。但是,用select的优势在于它可以同时处理多个连接,而阻塞IO只能处理一个。 例子:
Server端:
import select # 用来操作操作系统中的select(IO多路复用)机制
import socket sk = socket.socket()
sk.bind(('127.0.0.1',8888))
sk.setblocking(False)
sk.listen() r_lst = [sk,] while True:
# 监视r_lst这个列表(所有待接收请求的对象都在这里),谁的请求来了就通知谁,然后把有请求的对象返回给r_l列表,也有可能两个请求一起来
r_l,_,_ = select.select(r_lst,[],[])
for item in r_l: # 循环有请求的对象,判断是什么类型,进行对应的操作
if item is sk:
conn,addr = sk.accept()
r_lst.append(conn)
else:
try:
print(item.recv(1024))
item.send(b'hello')
except ConnectionResetError:
item.close()
r_lst.remove(item) Client端:
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',8888))
while 1:
sk.send(b'world')
print(sk.recv(1024)) 多路复用IO小结:
io多路复用(asycio tornado twisted)机制
select 在windows\mac\linux可用
底层是操作系统的轮询
有监听对象个数的限制
随着监听对象的个数增加,效率降低
poll 只在mac\linux可用
底层是操作系统的轮询
有监听对象个数的限制,但是比select能监听的个数多
随着监听对象的个数增加,效率降低
epoll 只在mac\linux可用
给每一个要监听的对象都绑定了一个回调函数
不再受到个数增加 效率降低的影响 socketserver机制
IO多路复用 + threading线程 selectors模块
帮助你在不同的操作系统上进行IO多路复用机制的自动筛选 4、异步IO(Asynchronous I/O)

用户进程发起请求之后,操作系统会立刻返回,所有不会形成阻塞,然后用户进程立刻就可以开始去做其它的事。同时操作系统会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,会给用户进程发送一个signal,告诉它操作完成了。

IO多路复用和local概念的更多相关文章

  1. linux select 与 阻塞( blocking ) 及非阻塞 (non blocking)实现io多路复用的示例

    除了自己实现之外,还有个c语言写的基于事件的开源网络库:libevent http://www.cnblogs.com/Anker/p/3265058.html 最简单的select示例: #incl ...

  2. linux select 与 阻塞( blocking ) 及非阻塞 (non blocking)实现io多路复用的示例【转】

    转自:https://www.cnblogs.com/welhzh/p/4950341.html 除了自己实现之外,还有个c语言写的基于事件的开源网络库:libevent http://www.cnb ...

  3. Java网络编程和NIO详解2:JAVA NIO一步步构建IO多路复用的请求模型

    Java网络编程与NIO详解2:JAVA NIO一步步构建IO多路复用的请求模型 知识点 nio 下 I/O 阻塞与非阻塞实现 SocketChannel 介绍 I/O 多路复用的原理 事件选择器与 ...

  4. 进击的Python【第十章】:Python的高级应用(多进程,进程间通信,协程与异步,牛逼的IO多路复用)

    Python的socket高级应用(多进程,协程与异步) 一.多进程multiprocessing multiprocessing is a package that supports spawnin ...

  5. IO多路复用技术总结

    来源:微信公众号「编程学习基地」 IO 多路复用概述 I/O 多路复用技术是为了解决进程或线程阻塞到某个 I/O 系统调用而出现的技术,使进程不阻塞于某个特定的 I/O 系统调用. 在IO多路复用技术 ...

  6. IO多路复用概念性

    sellect.poll.epoll三者的区别 先来了解一下什么是进程切换 为了控制进程的执行,内核必须有能力挂起正在CPU上运行的进程,并恢复以前挂起的某个进程的执行,这种行为为进程的切换,任务切换 ...

  7. IO多路复用之select总结

    1.基本概念 IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程.IO多路复用适用如下场合: (1)当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/ ...

  8. 【知乎网】Linux IO 多路复用 是什么意思?

    提问一: Linux IO多路复用有 epoll, poll, select,知道epoll性能比其他几者要好.也在网上查了一下这几者的区别,表示没有弄明白. IO多路复用是什么意思,在实际的应用中是 ...

  9. Python自动化之IO多路复用

    单线程.多线程和异步对比图 灰色的是阻塞 IO多路复用 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心 ...

随机推荐

  1. vue中如何使用mockjs摸拟接口的各种数据

    mockjs的作用 生成模拟数据 模拟 Ajax 请求,返回模拟数据 基于 HTML 模板生成模拟数据(后续更新) 帮助编写单元测试(后续更新) Vue 中使用 mock 有两种使用方式,一种是仅编写 ...

  2. HTML5利用canvas,把多张图合并成一张图片

    需求分析,根据当前网页中的几张图片,在手机上长按,保存图片到相册或者发送给好友. drawCanvas(){ var self = this; var imgsrcArray = [ require( ...

  3. angular打包后路由和文件路径不对

    base href换成如下script标签 <!-- <base href="/"> --> <script> document.write(' ...

  4. #WEB安全基础 : HTML/CSS | 0x4.1嵌套列表

    如果你认为列表只有ul和ol那你就错了 我要为你展示新的列表 这次只有一个index.html文件 这是它的效果 以下是它的代码 <html> <head> <title ...

  5. 解决 winform打开网页 和WebBrowser打开链接360误报拦截的问题

    以下方法我已经在自己电脑上验证通过,其他电脑并未测试,请广大读者自行验证并反馈,如果有更好的方法请指教. 在winform中如果使用这种方法弹出网页,例如这样 Process.start(" ...

  6. 智能POS(轻餐、正餐同理)桌台页面已结金额,只做参考,不做对账使用

    智能POS桌台已结金额只用来做参考使用,不做对账保障: 已结金额只有桌台一次结账金额,若存在反结账或退款的情况则不会减去相应的已结金额: 点餐无桌台的订单,金额不做统计: 口碑订单.扫码点餐,金额不做 ...

  7. python模块shutil

    shutil.copyfileobj(fsrc, fdst,[ length]) 拷贝文件句柄,将类文件对象fsrc的内容复制到类文件对象fdst.如果给定整数长度,则为缓冲区大小.如果长度是负值意味 ...

  8. 【原】Java学习笔记001 - JAVA开发环境搭建

    1.JDK下载并安装,以jdk-7u45-windows-i586.exe为例(注意JDK的安装和JRE的安装是分开的) 2.“我的电脑”右键属性,找到“高级系统设置”,找到“高级”tab下的“环境变 ...

  9. spring boot 中使用 jpa以及jpa介绍

    1.什么是jpa呢?JPA顾名思义就是Java Persistence API的意思,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中.12.jpa具有什么 ...

  10. mysql导出表的字段及相关属性

    需要导出数据库中表的字段及属性,制成表格保存到word中 首先找到要导的库, 在查询页面输入sql SELECT COLUMN_NAME 列名, COLUMN_TYPE 数据类型, DATA_TYPE ...