通過IO模型帶來的思考

尋箏發表於2018-08-29

IO模型

對於IO,我們經常可以聽到諸如同步阻塞IO,同步非阻塞IO,非同步IO等等,那麼什麼是非同步/同步,什麼是阻塞/非阻塞?首先一次IO在UNIX系統中分為兩個步驟

1.發起IO請求:使用者執行緒向作業系統核心發起IO請求

2.執行IO操作:當核心準備好資料可以提交給發起IO請求的執行緒

阻塞/非阻塞的區別:發起IO請求之後會一直等待直到獲取資料則是阻塞,否則是非阻塞

同步/非同步的區別:獲取到的資料是自己主動拿到的則是同步,是被動拿到的則是非同步

下面我用取快遞這個例子來介紹一下UNIX的五種IO模型

眾所周知吸管喝飲料分為兩個步驟:1.開啟快遞櫃(發起IO請求),2.取走快遞(執行IO操作)

同步&阻塞IO

開啟快遞櫃(發起IO請求),如果快遞櫃裡沒有東西(核心沒有準備好資料),則一直等在快遞櫃旁等快遞來(阻塞直到核心準備好資料),快遞櫃有了快遞則取走(使用者執行緒讀取核心中的資料)。

整個流程除了拿快遞,等快遞不能做其他事

同步&非阻塞IO

開啟快遞櫃(發起IO請求),如果快遞櫃裡沒有東西(核心沒有準備好資料),則馬上做其他事情每隔一段時間就去快遞櫃裡開啟看看是否有快遞(輪詢核心是否準備好資料),快遞櫃有了快遞則取走(使用者執行緒讀取核心中的資料)。

儘管這個模型相對同步阻塞IO效率有一定提升,但是大量的無用輪詢造成了CPU的空轉,很少使用這種IO模型

同步&多路複用IO

需要同時取N個快遞,派一個人幫你監視快遞櫃,告訴他你想要哪個快遞比如告訴他我要天貓的快遞,然後這個監視者一直站在快遞櫃旁邊等待天貓快遞到來並簽收,我們只需要向這個監視者拿快遞就行了。

這個模型中,監視者就是我們Java NIO中的Selector,一個執行緒阻塞同時監管多個執行緒連線狀態,返回給呼叫者連線狀態滿足所註冊的狀態條件連線執行緒。

同步&訊號驅動IO

在快遞櫃上寫上自己的手機號(回撥函式),當快遞送過來的時候直接給我打電話(執行回撥函式),然後我去取快遞。

非同步IO

假設收快遞的是一個國王,只需要叫一聲 我想要收到我的快遞,剩下的都不用國王自己操心了,會派人去快遞櫃門口等快遞,然後會有人幫忙把快遞送到手上(使用者執行緒)

思考

其實同步非同步/阻塞非阻塞並非只是在計算機的世界裡有,在網際網路時代,大部分的場景都在經歷IO模型之間的轉變

網購/外賣:就是一種非同步IO,商品(資料)從賣家/餐廳(核心態)被送貨員送到家(執行緒態),傳統的從家裡到餐廳然後吃飯,吃了回家,就是一種典型的同步阻塞IO。

滴滴叫車:是一種訊號驅動IO,在滴滴上下單過後就只需等待滴滴軟體提示(回撥函式)已經分配好司機並且正在來接你。傳統的方式則是自己要在路口等計程車/公交車,同步阻塞IO。

微信/簡訊:非阻塞同步IO,要通知其他人直接把資訊發出去就不用管了,一段時間去看看對方是否有回覆(輪詢)。而傳統的打電話則要確保對方接聽並將資訊告知對方,同步阻塞IO。

種植業:多路複用IO,比如farmer每天去看果園哪些蘋果紅了(滿足註冊的條件)就將紅蘋果收下來。如果種植業機械化程度夠高,則可以變成非同步IO的模式,種植,澆水,收割全部由機器完成。

等等

社會上所有能夠提升效率的場景,基本可以用IO模型去進行思考,演進過程也大致是從同步—》非同步,阻塞—》非阻塞


相關文章