.NET中的中并发编程-----阻塞与异步操作(二)

本文介绍了线程阻塞的原因,如线程同步Bug、死锁和IO操作,强调了CPU密集型任务适合多线程,而I/O密集型任务适合异步处理。文章探讨了事件循环如何实现异步操作,以及异步编程如何提高CPU利用率,减少线程等待,提高系统吞吐量。并提及了.NET中的异步支持,如Begin/End模式、EAP和Task异步编程模型。
摘要由CSDN通过智能技术生成

前言

  .NET中的中并发编程-----多线程、异步(一) 在前篇文章我们提到了线程阻塞(意味着被阻塞的线程暂停执行,不再占用 CPU 时间)的概念,多线程和异步的异同点,以及多线程和异步的使用场景,CPU密集型采用多线程;I/O密集型采用异步。

  那么是什么造成两者之间使用场景的差异呢?其实这一切都与阻塞息息相关。

三.线程阻塞形成的原因:

在了解异步操作的原理之前,让我们先来聊聊造成线程阻塞的几个主要原因:

  1.线程同步 Bug,如果一个线程锁定资源后忘记释放锁,其他请求该锁的线程就会进入阻塞状态。例如,笔者前文提到的session资源没有释放锁导致页面卡死的问题,就可以归类到此类里。

  2.线程发生死锁,多个线程竞争多个资源,如果线程不是以相同顺序依次锁定资源,就可能出现死锁的情况,这几个线程就会进入阻塞状态,没有机会再度运行。死锁问题咱们会在后文中继续讨论。

  3.CPU 读写比自己速度慢的设备,也就是 IO 操作,由于 IO 操作相对 CPU 执行指令慢得多,为了不浪费时间周期,不会选择啥也不干,一直等待 IO 操作结束,而是阻塞原有的线程,先去执行别的线程,直到那个 IO 操作完成,操作系统会再次调度执行阻塞的线程。如果由于意外故障,IO 极慢或者根本无响应,线程将会一直阻塞下去直到超时发生。如果这个故障短时间内未恢复,可能会造成线程池里的线程都阻塞,系统由于没有可执行线程,进入不响应的“卡死”状态。笔者前段时间就遇到过这样一个页面跳转时服务器崩溃的问题,排查后发现是在写一个设置了只读属性的xml文件时,文件无法读写,线程一直阻塞超时没有释放,最后导致iis线程池崩溃。

  不知道细心的读者注意到原因三了没有,当cpu进行IO操作,并不会让线程一直等待,而是会先阻塞线程,执行其他线程。

那么阻塞操作和异步操作的I/O密集的操作场景是不是有什么关系呢?

四.阻塞操作和事件循环是如何实现异步操作的:

    解答这个问题,请让我们先来了解一下异步操作的形成原理。

   在上文中,我们得知切换线程有一定的性能成本,并且线程可以进入休眠, 等待操作系统唤醒继续执行, 很多时候程序需要调用一些阻塞操作, 比如IO, 网络连接等, 需要让线程先等待, 操作完成之后重新把线程放入等待运行的队列等待唤醒执行。

  但是这样一旦阻塞操作很多, 意味着需要开启很多个线程, 开启线程的消耗会造成性能问题。

  为了解决这种问题, 最初是使用事件循环机制, 例如跨平台的select接口:

1)程序需要使用一个或多个线程用于获取事件

2)然后替换 执行阻塞操作 非阻塞操作。

3)注册事件用于在处理完成后接收通知。

  这样做的好处是发出阻塞操作的线程可以减少为1个, 这一个线程可以同时创建多个阻塞操作。然后在循环中不断处理事件, 针对不同事件, 及类似事件回调的数据, 执行对应的回调完成操作。

  基于事件循环编写程序有一定难度, 且代码结构类似, 因此在事件循环基础上封装了一套框架, 称为异步操作:

1)会先执行非阻塞操作,

2)注册事件关联回调,

3)接收到事件后自动调用之前关联的回调

小结

  通过上文我们可以发现,当其他硬件进行IO操作,比如网络请求中采用网卡中的DMA模式来进行IO操作时,异步编程是通过分工的方式,减少了CPU因线程等待的可能,让CPU一直处于工作状态,减少了CPU的压力。

  换句话说,异步其实是在提高cup的利用率,而不是节省线程。使用异步编程模型,虽然并不能加快程序本身的速度,但可以减少CPU空闲时间,只用很少的线程就可以达到超高的吞吐能力。

  在像消息队列这种业务逻辑简单并且需要超高吞吐量的场景下,或者必须长时间等待资源的地方,考虑使用异步模型。


  部分操作系统也提供了原生接口,如Windows的IOCP,Linux的AIO。以及其他著名的异步操作框架: C语言libevent,C++的ASIO,JAVA的Netty。.NET中的也提供了异步支持,1)Begin/End模式,2)EAP(Event-based Asynchronous Programming)基于事件的异步编程模式,3)基于任务异步编程模型,也就是我们熟悉的对象Task和Task<T>在关键字async和await。下文中会具体讨论Task,async,await,以及传统的thread和threadpool。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值