5G为数字化转型插上翅膀
|
因此,在基于事件驱动编程时有一条注意事项,那就是不允许发起阻塞式IO。 有的同学可能会问,如果不能发起阻塞式IO的话,那么该怎样进行IO操作呢? 有阻塞式IO,就有非阻塞式IO。 非阻塞IO 为克服阻塞式IO所带来的问题,现代操作系统开始提供一种新的发起IO请求的方法,这种方法就是异步IO,对应的,阻塞式IO就是同步IO,关于同步和异步这两个概念可以参考《从小白到高手,你需要理解同步与异步》。 异步IO时,假设调用aio_read函数(具体的异步IO API请参考具体的操作系统平台),也就是异步读取,当我们调用该函数后可以立即返回,并继续其它事情,虽然此时该文件可能还没有被读取,这样就不会阻塞调用线程了。此外,操作系统还会提供其它方法供调用线程来检测IO操作是否完成。 就这样,在操作系统的帮助下IO的阻塞调用问题也解决了。 基于事件编程的难点 虽然有异步IO来解决event loop可能被阻塞的问题,但是基于事件编程依然是困难的。 首先,我们提到,event loop是运行在一个线程中的,显然一个线程是没有办法充分利用多核资源的,有的同学可能会说那就创建多个event loop实例不就可以了,这样就有多个event loop线程了,但是这样一来多线程问题又会出现。 另一点在于编程方面,在《从小白到高手,你需要理解同步与异步》这篇文章中我们讲到过,异步编程需要结合回调函数(关于回调函数请才参考《程序员应如何彻底理解回调函数》),这种编程方式需要把处理逻辑分为两部分,一部分调用方自己处理,另一部分在回调函数中处理,这一编程方式的改变加重了程序员在理解上的负担,基于事件编程的项目后期会很难扩展以及维护。 那么有没有更好的方法呢?
要找到更好的方法,我们需要解决问题的本质,那么这个本质问题是什么呢? 当然关于IO多路复用技术的详细讲解请参见《终于明白了,一文彻底理解I/O多路复用》。 至此,关于利用事件驱动来实现并发编程的所有问题都解决了吗?event的来源问题解决了,当得到event后调用相应的handler,看上去大功告成了。 想一想还有没有其它问题? 问题:阻塞式IO 现在,我们可以使用一个线程(进程)就能基于事件驱动进行并行编程,再也没有了多线程中让人恼火的各种锁、同步互斥、死锁等问题了。 但是,计算机科学中从来没有出现过一种能解决所有问题的技术,现在没有,在可预期的将来也不会有。 那上述方法有什么问题吗? 不要忘了,我们event loop是运行在一个线程(进程),这虽然解决了多线程问题,但是如果在处理某个event时需要进行IO操作会怎么样呢? 在《读取文件时,程序经历了什么》一文中,我们讲解了最常用的文件读取在底层是如何实现的,程序员最常用的这种IO方式被称为阻塞式IO,也就是说,当我们进行IO操作,比如读取文件时,如果文件没有读取完成,那么我们的程序(线程)会被阻塞而暂停执行,这在多线程中不是问题,因为操作系统还可以调度其它线程。
但是在单线程的event loop中是有问题的,原因就在于当我们在event loop中执行阻塞式IO操作时整个线程(event loop)会被暂停运行,这时操作系统将没有其它线程可以调度,因为系统中只有一个event loop在处理用户请求,这样当event loop线程被阻塞暂停运行时所有用户请求都没有办法被处理,你能想象当服务器在处理其它用户请求读取数据库导致你的请求被暂停吗? (编辑:平顶山站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


