這幾天詳細(xì)讀了muduo的網(wǎng)絡(luò)處理部分评甜,發(fā)現(xiàn)多線程處理是整個(gè)框架的精華肘交。muduo是基于one loop per thread模型的氯窍。那么什么是one loop per thread模型呢缔杉?
字面意思上講就是每個(gè)線程里有個(gè)loop,即消息循環(huán)锤躁。我們知道服務(wù)器必定有一個(gè)監(jiān)聽的socket和1到N個(gè)連接的socket,每個(gè)socket也必定有網(wǎng)絡(luò)事件或详。我們可以啟動(dòng)設(shè)定數(shù)量的線程系羞,讓這些線程來承擔(dān)網(wǎng)絡(luò)事件郭计。
每個(gè)進(jìn)程默認(rèn)都會(huì)啟動(dòng)一個(gè)線程,即這個(gè)線程不需要我們手動(dòng)去創(chuàng)建椒振,稱之為主線程昭伸。一般地我們讓主線程來承擔(dān)監(jiān)聽socket的網(wǎng)絡(luò)事件。至于連接socket的事件要不要在主線程中處理澎迎,這個(gè)得看我們啟動(dòng)其他線程即工作線程的數(shù)量庐杨。如果啟動(dòng)了工作線程,那么連接socket的網(wǎng)絡(luò)事件一定是在工作線程中處理的夹供。
每個(gè)線程的事件處理都是在一個(gè)EventLoop的while循環(huán)中灵份,而每一個(gè)EventLoop都有一個(gè)多路事件復(fù)用解析器epoller。循環(huán)的主體部分是等待epoll事件觸發(fā)哮洽,從而處理事件填渠。主線程EventLoop的epoller會(huì)添加監(jiān)聽socket可讀事件,而工作線程只添加了定時(shí)器處理事件(每個(gè)EventLoop都會(huì)有鸟辅,主線程有EventLoop,當(dāng)然也添加了定時(shí)器處理事件)氛什。在沒有事件觸發(fā)之前,epoller都是阻塞的匪凉,導(dǎo)致線程被掛起枪眉。
當(dāng)有連接來到時(shí),掛起的主線程恢復(fù)洒缀,會(huì)執(zhí)行新連接的回調(diào)函數(shù)瑰谜。在該函數(shù)中,會(huì)從線程池中取得一個(gè)線程來接管新連接socket的處理树绩。那么問題來了,既然工作線程已經(jīng)阻塞了隐轩,那他是如何處理新連接socket相關(guān)事件的呢饺饭,也就是什么時(shí)候恢復(fù)呢?
原來职车,每個(gè)EventLoop還有一個(gè)wakeup事件瘫俊。主線程通知工作線程去處理事件的時(shí)候,工作線程發(fā)現(xiàn)不在本線程的時(shí)間片中悴灵,于是喚醒工作線程了扛芽。
有關(guān)代碼,下篇再分析积瞒。