翻译 异步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中我们列出了进程和线程相对应的控制原语. ...
随机推荐
- VUE2+elementUI前端实现 三级省市联动select
html: <el-form-item label="选择地区:"> <el-select size="small" style=" ...
- c++ a+b
#include<iostream> using namespace std; int main() { int a,b,sum; cin>>a>>b; sum=a ...
- 更换MariaDB数据库
https://downloads.mariadb.org/mariadb/repositories/#mirror=neusoft&distro=Ubuntu&distro_rele ...
- 最简单的原生js和jquery插件封装
最近在开发过程中用别人的插件有问题,所以研究了一下,怎么封装自己的插件. 如果是制作jquery插件的话.就将下面的extend方法换成 $.extend 方法,其他都一样. 总结一下实现原理: 将 ...
- HTML/CSS实现的一个列表页
又到休息日,白天没事跟朋友去逛逛街,侃大山,晚上了,上网无趣,于是就想起该练练了, 这次是做了一个页面,最上面是一个banner 用到了一个jQuery的逻辑判断当banner初始top值小于wind ...
- kodexplorer免费网盘安装教程
KodExplorer是什么? KodExplorer可道云,原名芒果云,是基于Web技术的私有云和在线文件管理系统. 用户只需通过简单环境搭建,即可使用KodExplorer快速完成私有云/私有网盘 ...
- 771. Jewels and Stones
You're given strings J representing the types of stones that are jewels, and S representing the ston ...
- 04.封装ajax
<script> //封装ajax // 函数名 ajax // 函数的参数 // url: 请求的地址 // type: 请求的方式 get /post // data: 要上传的数据 ...
- git 服务器搭建与运用
环境:CentOS 6 为了不影响后面的安装 安装依赖库 yum install curl-devel expat-devel gettext-devel openssl-devel zlib-dev ...
- Java作业九(2017-11-6)
/*圆的类*/ public class R { private double radius; // 构造方法,有参构造 public R(double radius) { this.radius = ...