由阻塞IO延伸出来的学习

  网上有很多讨论IO阻塞非阻塞,同步异步的文章,说阻塞IO影响了服务性性能,所以现在使用NIO(非阻塞)可以有效优化。但又查了很多资料,明确表示如果线程是blocked状态,是不消耗cpu资源的,监视屏是不会分配给blocked状态的线程cpu时间片的。而线程的blocked状态可以由IO阻塞引起,也可以是其他原因。那么问题来了,如果真的阻塞式IO把线程状态变成了Blocked,cpu就会忽略这个线程,何来性能下降之说呢。

  找到一个解释:


The Java system has two distinct threading models. The simplest and preferred model supports LWTs (light weight threads). In this model, CLDC HotSpot Implementation implements all LWTs on a single native OS thread. LWTs are essentially co-routines created and scheduled by the virtual machine. This is transparent at the Java runtime environment level.
...
A special style of handling threading might be preferable in some ports. This style relies on the availability of native thread support in the target platform OS. It is called hybrid threading

也就是说java有两种线程模型,一种是自己代码控制的应用级线程,一种是操作系统的原生线程: http://www.cnblogs.com/onlywujun/articles/5183281.html

采用哪种方式,由虚拟机自己决定。

如果采用用户线程,则遵守co-routines规则来创建这些轻量级线程(LWTs),许多这种线程在一个真正的原生线程里运行。cpu执行的是原生线程,也并不知道里面包含了什么。

所以这种LWTs线程中如果有IO堵塞,就会占用cpu资源。

而另一种方式生产的原生线程如果IO阻塞则不会占用cpu资源(内存肯定是会占用的,因为有栈嘛)。因为这个线程是真正到了blocked状态。

 

现在我算是明白了所谓的阻塞IO,就是指程序在代码级运行过程中,有IO操作的时候,发出IO指令后,要不要等IO完成再执行下一步。我们常写的代码都是阻塞式的编程方式,这样代码顺序是流式的,逻辑很清晰。这种编程风格就是使用co-routine规范来完成的。

那么非阻塞IO就是指这个代码逻辑在IO没有完成的时候就直接往后面执行。

其实在javaScript里就很常见了,ajax请求有“同步”,“异步”两种,其实就是上面的意思。

网上很多争论同步/异步和阻塞/非阻塞的概念。其实都不是同一个层面的东西。同步/异步可以理解为两个人在交接一个东西的时候的对接方式,如果是手把手的传递就是同步,如果是一个人把东西托第三人代给对方就是异步。

在上面ajax请求的例子里,发一个http请求,客户端如果直接发到服务器就是同步的,如果通过了代理就是异步的。(ajax的同步和异步准确的说应该是阻塞和非阻塞,这里误导了好多人,导致网上五花八门的说法。)

所以阻塞/非阻塞是指自己处理自己事情的方式,同步/异步是指与别人发生交互的方式。(这个是自己不可控,因为调度权交出去了。)

 

那么如果采用NON Block IO ,就要使用操作系统的原生线程去执行这个IO。编程风格也相应要变成回调callBack式的了。如果一大段代码都是这种回调式的,可读性就非常不好了。

 

-------

其实说阻塞IO问题主要是大并发性能低。应用级的原因就是web服务器对每一个http请求都使用一个线程来处理。这些线程都在服务器的线程池里进行管理,但都有一个最大数量。阻塞IO会持有一个线程不放回池子里,如果多了就没有空闲的线程可用了。

而采用非阻塞IO的服务器使用的策略则是使用java的nio包的API,如果发生IO阻塞了,就把阻塞之后的执行逻辑作为回调函数放进待执行队列中,然后把运行这个请求的线程放行,让这个线程回到线程池里,就可以立即使用了。待事件触发可以执行了,再从线程池里取一个线程来执行。这样服务器的线程有没有消耗在等待的时间上了。

而放在那个等待触发队列里的那些执行逻辑,我猜得没错的话,就是使用了操作系统级的线程了,并让它们处于blocked状态等待触发重新回到运行状态的事件。

以前我看见别人评价nio一句话:就是把虚拟机的线程改用成系统线程了,现在算是明白了。

 

posted @ 2016-02-05 16:50  寂静沙滩  阅读(296)  评论(0)    收藏  举报