异步事件回调机制原理探索 (转)

http://blog.csdn.net/blues1021/article/details/44276085

软件组件之间,函数之间的调用分为:同步调用,函数指针形式的同步回调,异步调用。前面两种很简单无需多言,这里只探索下异步调用。

自定义的异步事件回调机制:

可以在自己的应用程序中,先注册事件和事件对应的回调函数(回调函数可以是函数指针法,虚函数方法的方式);自己程序中每帧检测事件是否发生或者条件是否满足,满足的时候就进入回调函数。如果这样的检查是在同一个线程中那么就是同步的延迟调用,如果是在子线程中就是异步调用,但是这样的性能还是比较差的,除非不得以,否则还是用OS的异步回调机制性能高。

OS层面的异步事件回调机制:

linux下的异步回调机制:

1.异步事件的注册:会在内核里面产生一个事件放置到事件队列(属于内核事件或者线程/进程事件队列,加入事件select,poll是O(n)算法效率,epoll是O(1)算法效率因为使用了mmap不需要从用户空间拷贝到内核空间,其它事件类似);2.异步事件的检测:检查时候会查询内核中的线程/进程事件队列(select,poll是O(n)算法效率,epoll是O(1)算法效率应该使用了数组类型的数据结构存储映射关系,其它事件类似 );阻塞线程/进程如果存在满足事件那么马上返回结果。 非阻塞的线程/进程条件满足返回结果,条件不满足那么返回非阻塞的信息,可以继续做其它事情

3.异步事件的回调驱动:文件设备驱动程序内有读写队列,当读写队列资源变为可读or写的时候(进程继续执行(或发出事件通知到内核事件队列/线程进程的事件队列中)。唤醒后会再次判断文件设备条件是否满足因为非独占的资源可能被其它线程/进程获取了; 阻塞条件下成功了马上执行异步回调,返回中断现场继续执行程序逻辑,非阻塞条件下线程执行到此处检查事件队列将会成功从而产生异步调用,返回当时中断现场执行条件满足的后续逻辑,unity3d的coroutine也是这样的原理

回调事件注册和异步事件的驱动都和linux下类似。
只是检查异步事件的消息, windows内核有一个事件队列,内核也为当前的用户线程创建事件队列,当内核驱动触发事件(周期触发或OS通知触发)时,消息会被分发到内核事件队列,分发到当前线程事件队列;当前线程需要一个消息循环不断的获取消息,当然也提供了阻塞模式和非阻塞模式的检测消息(getmessage没有获得去到消息会阻塞挂起当前线程,peekmessage没有获取到消息返回FALSE不会阻塞挂起当前线程),接收到了消息要进行分发处理。
如图:

为了更清楚地说明这个问题,我们参看图1:




==================

http://www.cnblogs.com/DebugLZQ/archive/2012/09/05/2670986.html

最近很忙,因此拿出时间来写博客也算是忙里偷闲了,继承前面的一贯风格,继续浅谈胡侃。
  最近在项目中遇到了Socket异步网络传输的问题,所以沉下心来整理下。于是,先问了下度娘,结果找到了园友志良的一篇文章《C#中异步和多线程的区别》(参考文献1),精读了一遍,个人觉得理解的很好,自己学习下之余,又动手加工了一下以分享给各位博友,希望各位博友能对异步和多线程有一个清楚的认识。

  C#中异步和多线程的区别是什么呢?异步和多线程两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性。甚至有些时候我们就认为异步和多线程是等同的概念。但是,异步和多线程还是有一些区别的。而这些区别造成了使用异步和多线程的时机的区别。  

  异步操作的本质

  所有的程序最终都会由计算机硬件来执行,所以为了更好的理解异步操作的本质,我们有必要了解一下它的硬件基础。 熟悉电脑硬件的朋友肯定对DMA这个词不陌生,硬盘、光驱的技术规格中都有明确DMA的模式指标,其实网卡、声卡、显卡也是有DMA功能的。DMA就是直 接内存访问的意思,也就是说,拥有DMA功能的硬件在和内存进行数据交换的时候可以不消耗CPU资源。只要CPU在发起数据传输时发送一个指令,硬件就开 始自己和内存交换数据,在传输完成之后硬件会触发一个中断来通知操作完成。这些无须消耗CPU时间的I/O操作正是异步操作的硬件基础。所以即使在DOS 这样的单进程(而且无线程概念)系统中也同样可以发起异步的DMA操作。

  线程的本质

  线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度。

  异步操作的优缺点

  因为异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少 共享变量的数量),减少了死锁的可能。当然异步操作也并非完美无暇。编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些出入,而且难以调试。

  多线程的优缺点

  多线程的优点很明显,线程中的处理程序依然是顺序执行,符合普通人的思维习惯,所以编程简单。但是多线程的缺点也同样明显,线程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现。

  适用范围

  在了解了线程与异步操作各自的优缺点之后,我们可以来探讨一下线程和异步的合理用途。我认为:当需要执行I/O操作时,使用异步操作比使用线程+同步 I/O操作更合适。I/O操作不仅包括了直接的文件、网络的读写,还包括数据库操作、Web Service、HttpRequest以及.net Remoting等跨进程的调用。

  而线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。但是往往由于使用线程编程的简单和符合习惯,所以很多朋友往往会使用线程来执行耗时较长的I/O操作。这样在只有少数几个并发操作的时候还无伤大雅,如果需要处理大量的并发操作时就不合适了。

  异步的一个示例

  大家可能都知道,使用delegate可以“自动”使一个方法可以进行异步的调用。从直觉上来说,我觉得是由编译器或者CLR使用了另外的线程来执行目标方法。到底是不是这样呢?




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值