node特点就是单线程,异步,回调,适合高并发的环境。
单线程就是指我们的所有代码单线程执行的,就是指在同一时间node只能执行一条代码。
- 产生的问题就是:单线程怎么实现异步呢?
回答:
node本身是单线程的,但是它所运行的环境并不是单线程的,它会维护一个队列,循环检测,调度JS线程来执行。
- 问题:既然单线程同一时间只能执行一条代码,那么为什么他会更适合高并发的情况呢?而不是多线程同时执行更适合高并发呢?
回答:
I/O操作并不调用CPU,在
高并发I/O密集型应用 中,如果采用多线程阻塞,频繁的I/O操作会阻塞每一条线程,导致CPU可能不能一直运转,但是如果是单线程非阻塞的话,I/O操作只是一个传给操作系统的通知,然后继续使用CPU,等到I/O操作结束了,再使用CPU对I/O的结果进行计算。在
高CPU型 的应用中,node单线程面临的挑战就是如果长时间进行计算那么会导致后面的代码无法执行,也算一中变相的阻塞吧。这样并发的时候可能就会阻塞其他用户了。
阻塞:
什么叫阻塞(block)?线程在执行中如果遇到I/O操作(磁盘读写、网络通信等)通常需要耗费较长的时间,这时候操作系统会剥夺线程对CPU的控制权,使其暂停,并把资源让给其它的工作线程(这样I/O操作后的那些代码就无法执行了,等待I/O结束后才能继续利用CPU),这种线程调度方式成为阻塞。
当I/O操作完毕的时候操作系统将这个线程的阻塞状态解除,恢复其对CPU的控制权,令其继续执行,这种I/O模式就是同步I/O或成为阻塞I/O。
非阻塞
:
响应的异步I/O或非阻塞I/O则针对所有的I/O操作采取不阻塞的策略,当线程遇到I/O操作时不会以阻塞的方式等待I/O操作结束,而只是将I/O请求发送给操作系统,继续执行后续语句。当操作系统完成I/O操作时以事件的形式通知执行I/O操作的线程,线程会在特定时间处理这个事件。为了处理异步I/O必须有
事件循环
,不断检查有没有未处理的事件,依次予以处理。
非阻塞与阻塞的对比:
在阻塞模式下,一个线程只能处理一个任务,要想提高吞吐量必须通过多线程。而在非阻塞模式下一个线程永远在执行计算操作,这个线程所使用的CPU核心利用率永远是100%,I/O以事件的方式通知。在阻塞模式下多线程往往能够提高系统吞吐量,因为一个线程阻塞时还有其他线程在工作,多线程可以让CPU资源不被阻塞的线程浪费。而在非阻塞模式下,线程不会被I/O阻塞,永远在利用CPU。异步I/O减少了多线程中创建线程、分配内存、列入调度、切换线程、内存换页、CPU缓存等方面的开销。