Java I/O模型

同步 vs. 異步

同步I/O 每個(gè)請(qǐng)求必須逐個(gè)地被處理,一個(gè)請(qǐng)求的處理會(huì)導(dǎo)致整個(gè)流程的暫時(shí)等待,這些事件無(wú)法并發(fā)地執(zhí)行。用戶線程發(fā)起I/O請(qǐng)求后需要等待或者輪詢內(nèi)核I/O操作完成后才能繼續(xù)執(zhí)行。

異步I/O 多個(gè)請(qǐng)求可以并發(fā)地執(zhí)行,一個(gè)請(qǐng)求或者任務(wù)的執(zhí)行不會(huì)導(dǎo)致整個(gè)流程的暫時(shí)等待。用戶線程發(fā)起I/O請(qǐng)求后仍然繼續(xù)執(zhí)行,當(dāng)內(nèi)核I/O操作完成后會(huì)通知用戶線程,或者調(diào)用用戶線程注冊(cè)的回調(diào)函數(shù)。

阻塞 vs. 非阻塞

阻塞 某個(gè)請(qǐng)求發(fā)出后,由于該請(qǐng)求操作需要的條件不滿足,請(qǐng)求操作一直阻塞,不會(huì)返回,直到條件滿足。

非阻塞 請(qǐng)求發(fā)出后,若該請(qǐng)求需要的條件不滿足,則立即返回一個(gè)標(biāo)志信息告知條件不滿足,而不會(huì)一直等待。一般需要通過(guò)循環(huán)判斷請(qǐng)求條件是否滿足來(lái)獲取請(qǐng)求結(jié)果。

需要注意的是,阻塞并不等價(jià)于同步,而非阻塞并非等價(jià)于異步。事實(shí)上這兩組概念描述的是I/O模型中的兩個(gè)不同維度。

同步和異步著重點(diǎn)在于多個(gè)任務(wù)執(zhí)行過(guò)程中,后發(fā)起的任務(wù)是否必須等先發(fā)起的任務(wù)完成之后再進(jìn)行。而不管先發(fā)起的任務(wù)請(qǐng)求是阻塞等待完成,還是立即返回通過(guò)循環(huán)等待請(qǐng)求成功。

而阻塞和非阻塞重點(diǎn)在于請(qǐng)求的方法是否立即返回(或者說(shuō)是否在條件不滿足時(shí)被阻塞)。

Unix下五種I/O模型

Unix 下共有五種 I/O 模型:

  • 阻塞 I/O

  • 非阻塞 I/O

  • I/O 多路復(fù)用(select和poll)

  • 信號(hào)驅(qū)動(dòng) I/O(SIGIO)

  • 異步 I/O(Posix.1的aio_系列函數(shù))

阻塞I/O

如上文所述,阻塞I/O下請(qǐng)求無(wú)法立即完成則保持阻塞。阻塞I/O分為如下兩個(gè)階段。

  • 階段1:等待數(shù)據(jù)就緒。網(wǎng)絡(luò) I/O 的情況就是等待遠(yuǎn)端數(shù)據(jù)陸續(xù)抵達(dá);磁盤I/O的情況就是等待磁盤數(shù)據(jù)從磁盤上讀取到內(nèi)核態(tài)內(nèi)存中。

  • 階段2:數(shù)據(jù)拷貝。出于系統(tǒng)安全,用戶態(tài)的程序沒(méi)有權(quán)限直接讀取內(nèi)核態(tài)內(nèi)存,因此內(nèi)核負(fù)責(zé)把內(nèi)核態(tài)內(nèi)存中的數(shù)據(jù)拷貝一份到用戶態(tài)內(nèi)存中。

非阻塞I/O

非阻塞I/O請(qǐng)求包含如下三個(gè)階段

  • socket設(shè)置為 NONBLOCK(非阻塞)就是告訴內(nèi)核,當(dāng)所請(qǐng)求的I/O操作無(wú)法完成時(shí),不要將線程睡眠,而是返回一個(gè)錯(cuò)誤碼(EWOULDBLOCK) ,這樣請(qǐng)求就不會(huì)阻塞。

  • I/O操作函數(shù)將不斷的測(cè)試數(shù)據(jù)是否已經(jīng)準(zhǔn)備好,如果沒(méi)有準(zhǔn)備好,繼續(xù)測(cè)試,直到數(shù)據(jù)準(zhǔn)備好為止。整個(gè)I/O 請(qǐng)求的過(guò)

    網(wǎng)友評(píng)論