翻译 异步I/O不会创建新的线程
异步I/O不会创建新的线程
本文翻译自 Stephen Cleary 的 [There is No Thread] 原文地址 https://blog.stephencleary.com/2013/11/there-is-no-thread.html
这是异步编程最基本的事实 : 异步I/O不会创建新的线程
反对这个事实的人很多,他们对此的看法是 "如果我await一个操作,那么一定会有一个线程正在等待,它可能是一个线程池的线程,或者是操作系统线程,或者是某个设备的驱动程序"
不用关注这些看法, 只需要记住如果异步操作是纯粹的(方法全是async),那么就不会产生新的线程
不过这么一个简单的结论显然并不能够让他们信服,下面就看看异步到底发生了什么
让我们跟踪一个异步操作直到硬件层面,注:Net部分和设备驱动部分将被简化描述 (因为细节太多了)
下面是一个通用的写入操作 (例如 文件、网络、USB面包机等等)
private async void Button_Click(object sender, RoutedEventArgs e)
{
byte[] data = ...
await myDevice.WriteAsync(data, 0, data.Length);
}
我们已经知道在await的时候UI线程不会被阻塞,那么问题来了: 是否是UI线程创建了另外一个线程杀了祭天换来了自己的自由....
关于UI线程是否犯下这一恶行,让我们深入推断一下
首先 : 看看类库 (BCL的代码) 假设 WriteAsync 是使用.Net中标准的异步方式平台调用(P/Invoke)I/O系统,这是一个基于异步方式的I/O,所以这会在设备的底层上启动一个win32异步方式I/O操作句柄
然后操作系统会告诉设备驱动程序进行写操作,代码实现是构造出表示写请求的对象,这个对象称为I/O请求包(IRP)
设备驱动程序接收到IRP后会向设备发出一个命令来写出数据,如果这个设备支持直接内存存取技术(DMA),只需将缓冲区地址写入设备寄存器即可,设备驱动程序能做到将IRP标记为 "pending" 后交把控制权交还操作系统
在这里发现了真相的核心所在 : 在处理IRP时,设备驱动是不允许阻塞的。这意味着如果IRP不能立即完成,那么它必须异步处理,即使对于同步的api也是如此!在设备驱动级别,所有(有意义)的请求都是异步的
引用书籍里的知识 "无论是什么类型的I/O请求,应用程序向驱动程序发出的I/O操作都是异步执行的"
在IRP为 "pending" 时,操作系统返回到类库,类库将未完成的任务返回到应用程序的按钮单击事件方法,该方法挂起async方法,UI线程继续执行
我们已经跟踪请求到系统的尽头 直到物理设备
现在写入操作正在飞快的进行中,有多少个线程正在处理它?
答案是没有
没有设备驱动程序线程、操作系统线程、BCL线程或者写在处理写操作的线程池线程(
翻译 异步I/O不会创建新的线程的更多相关文章
- nodejs中使用worker_threads来创建新的线程
目录 简介 worker_threads isMainThread MessageChannel parentPort和MessagePort markAsUntransferable SHARE_E ...
- 【C++】【MFC】创建新的线程函数
DWORD WINAPI MyThreadProc (LPVOID lpParam){ somestruct* pN = (somestruct*)lpParam; // 将参数转为你的类型 ... ...
- 多线程编程之Windows环境下创建新线程
转自: http://www.cnblogs.com/lgxqf/archive/2009/02/10/1387480.html 在 Win32 API 中,创建线程的基本函数是 CreateThre ...
- Spark无法创建新线程
Spark提交程序报错,无法创建新的线程 原因是因为这台公用机器上跑的进程太多了,需要修改Linux参数,允许用户最大进程数 查看允许用户最大进程数配置 ulimit -a 修改允许用户最大进程数配置 ...
- Java多线程-新特性-线程池
Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定可靠的多线程程序 ...
- JVM最多能创建多少个线程:unabletocreatenewnativethread
最近需要测试一个长连接服务器,数据上需要达到100W的长连接,测试的客户端,一个线程保持一个连接,发现linux服务器默认创建到3200多个线程的时候,就会报错这个错误“java.lang.OutOf ...
- Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner-X线程
待解决的问题 Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner-X线程 解决办法 为spring session添加spr ...
- Linux 循环创建多个线程
这里说一下相关的基础知识: 线程概念 什么是线程 LWP:light weight process 轻量级的进程,本质仍是进程(在Linux环境下) 进程:独立地址空间,拥有PCB 线 ...
- UNIX环境编程学习笔记(26)——多线程编程(一):创建和终止线程
lienhua342014-11-08 在进程控制三部曲中我们学习了进程的创建.终止以及获取终止状态等的进程控制原语.线程的控制与进程的控制有相似之处,在表 1中我们列出了进程和线程相对应的控制原语. ...
随机推荐
- Xcode 10.1 运行老版本工程遇到问题解决记录
近来接手公司一个历史遗留项目进行修改.上线工作,想想我都近三年没敲过iOS代码了也是慌.. 项目大致情况: 18年年初应上线项目,各种情况下一直搁置,到18年底了要重启上线,原来开发人员离职了都,年底 ...
- WinCC OA基本概念
WinCC OA 是一个模块化软件架构的系统.所需的功能由不同任务创建的特定单元处理.在WinCC OA中,这些单元称为管理器 - 管理器是软件自身的一些独立的处理过程. 图:WinCC OA系统由功 ...
- 关机,重启BAT命令
关机命令shutdown -s -t 重启命令 shutdown -r -t
- VMware workstation pro 15 安装Ubuntu(图文教程)
今天分享一下虚拟机安装Ubuntu的过程,在开始安装之前,需要下载VMware workstation pro和Ubuntu镜像,两者我都用的最新版,由于VMware workstation pro ...
- 使用ant编译zookeeper源码
1. 安装Ant Ant下载地址:http://ant.apache.org/bindownload.cgi 解压即可. 注意如果不配置环境变量的话需要使用绝对路径,我配置了. 开始我ant跑错了 U ...
- U-Boot内存管理
如<Linux内核内存管理架构>一文中提到,linux内核中的内存管理支持内存地址映射.内存分配.内存回收.内存碎片管理.页面缓存等众多功能.但U-Boot做为启动引导程序,其核心功能就是 ...
- Linux下Shell重定向
1. 标准输入,标准输出与标准错误输出 Linux下系统打开3个文件,标准输入,标准输出,标准错误输出. 标准输入:从键盘输入数据,即从键盘读入数据. 标准输出:把数据输出到终端上. 标准错误输出:把 ...
- PHP调用微信wx_JSSDK录音并播放,
<?php require_once "jssdk.php"; $jssdk = new JSSDK("wx7a862ec806328ca2", &quo ...
- 关于vue的数据增删的一些细节
第一种情况:在vue中使用的数据必须先在data中定义数据,不然报错: 第二种情况:访问对象中不存在的值,是可以得到undefined,但是不会报错 第三种:vue只会监听data已经定义的值,后续添 ...
- python语法_json_pickle
---恢复内容开始--- dic = {"name":"kevin","age":"20"} f = open(&quo ...