Nodejs編程是全異步的,這就意味著我們不必每次都阻塞等待該次操作的結(jié)果,而事件完成(就緒)時會主動回調(diào)通知我們。在網(wǎng)絡編程中,一般都是基于Reactor線程模型的變種,無論其怎么演化,其核心組件都包含了Reactor實例(提供事件注冊、注銷、通知功能)、多路復用器(由操作系統(tǒng)提供,比如kqueue、select、epoll等)、事件處理器(負責事件的處理)以及事件源(linux中這就是描述符)這四個組件。一般,會單獨啟動一個線程運行Reactor實例來實現(xiàn)真正的異步操作。但是,依賴操作系統(tǒng)提供的系統(tǒng)調(diào)用來實現(xiàn)異步是有局限的,比如在Reactor模型中我們只能監(jiān)聽到:網(wǎng)絡IO事件、signel(信號)、超時事件以及一些管道事件等,但這些事件也只是通知我們資源可讀或者可寫,真正的讀寫操作(read和write)還是同步的(也就是你必須等到read或者write返回,雖然linux提供了aio,但是其有諸多槽點),那么Nodejs的全異步是如何做到的呢?你可能會很快想到,就是啟用單獨的線程來做同步的事情,這也是libuv的設(shè)計思路,借用官網(wǎng)的一張圖,說明一切:
由上圖可以看到,libuv實現(xiàn)了一套自己的線程池來處理所有同步操作(從而模擬出異步的效果),下面就來看一下該線程池的具體實現(xiàn)吧!
一、線程池模型
說道線程池,在java領(lǐng)域中,jdk本身就提供了多種線程池實現(xiàn),幾乎所有的線程池都遵循以下模型(任務隊列+線程池):
libuv自身定義了一個非常精煉、高效的隊列(雙向循環(huán)鏈表),只用了幾個簡單的宏定義將其實現(xiàn),具體實現(xiàn)方式可以參見我的另一篇博文:libuv高效隊列的實現(xiàn)?,F(xiàn)在隊列有了,來看一下task的定義:
1 struct uv__work { 2 void (*work)(