為了改善多程序和多執行緒實現伺服器不停地建立刪除程序或執行緒給系統帶來的負擔,引進了執行緒池,程序池來改善此種情況,此處以執行緒池為例。執行緒池的優勢:
(1)、建立的程序或者執行緒是有限的,伺服器的系統代價比較小,一般不會到達系統限制的值。
(2)、伺服器不需要頻繁的建立、銷毀程序或者執行緒,只在伺服器啟動時建立,結束時銷毀。
(3)、建立的程序或者執行緒不是為乙個客戶端服務,可以序列為多個客戶端服務。
(4)、客戶端連線上以後,不需要再去建立程序或者執行緒,只需要分配程序池或者執行緒池中的程序或執行緒,減少了客戶端等待的時間。
執行緒池的邏輯(偽**):
具體**:
#include #include #include #include #include #include #include #include #include #include #include #define threadnum 3
#define clientnum 10
sem_t sem;
pthread_mutex_t mutex;
int clientfds[clientnum];
void init_clientfds()
}void insert_client(int fd)
} pthread_mutex_unlock(&mutex);
}int get_client()
} pthread_mutex_unlock(&mutex);
return c;
}void * dealclient(void * arg)
; int n = recv(c, data, 127, 0);
if(n <= 0)
printf("%s\n", data);
send(c, "ok", 2, 0);
} }}int main()
while(1)
}
**優化:
我們為了儲存檔案描述符維護了乙個陣列,在**中插入獲取時都是從[0]遍歷獲取,加入56789,再取出56,此時又插入了10,那麼下一次就會對10先進行操作,使後面的fd等待太久,因此對於**中的getclientfds()做了優化。
int getclientfds() //只需將每次獲取時整體向前挪乙個單元格
clientfds[i] = -1;
pthread_mutex_unlock(&mutex);
return c;
}
維護檔案描述符陣列的方式:
第①種方式:
優點:只要陣列中有fd就能立即處理
缺點:當fd插入不是很頻繁的時候,會出現一直只呼叫第乙個函式執行緒的情況,其他的函式執行緒一直未使用,造成資源的浪費。
第②種方式:
優點:只要分配合理,每一條執行緒都能得到利用
缺點:當其中的乙個子執行緒fd處理比較麻煩時,後面分配給他的fd會滯留在陣列中得不到及時的處理
相對比①②來說,②的處理方法更合理一些,這種方法可以做到負載均衡
程序池和執行緒池的問題:
程序池和執行緒池相比於多程序多執行緒有所改善,但當乙個執行緒為乙個客戶端服務時,只能等客戶端退出,才能服務下乙個客戶端,有可能出現客戶端佔著資源不使用,阻塞在recv函式的情況,對執行緒也是一種浪費,程序池同理,這種情況是之前提到伺服器的通病,在select,poll,epoll,這三種方法建立的伺服器會將這個問題解決。
高效能伺服器程式設計 執行緒池
在我們之前所講述過的以poll方式實現tcp伺服器流程,我們仔細研究一下會發現,客戶端的資料我們還是以序列的方式來處理的。由此我們提出了以多程序或者多執行緒的方式來加以實現是不是會更好。比如採用多程序的方式 但是這種方式還是會有bug出現,比如有僵死程序的情況出現和建立程序的代價很大等情況發生。此處...
高效能伺服器程式設計 程序池 執行緒池
高效能伺服器程式設計主要分為多程序和多執行緒 程序池和執行緒池,用來處理乙個服務程式能夠同時處理多個客戶連線的問題。我們首先回顧下多程序和多執行緒的知識,因為程序池和執行緒池是在這個基礎上進行改進的,也是伺服器用的比較多的。多程序 accept 建立子程序,由子程序和客戶端通訊。父程序繼續接受客戶連...
高效能伺服器程式設計 程序池或執行緒池
一般來說,伺服器的硬體資源相對充裕,很多時候都用空間換時間的方法來提高伺服器的效能,不惜浪費大量的空間資源來換取伺服器的執行效率。具體做法 提前申請大量的資源,以備不時之需以及重複使用。這就是池的概念 池其實就是一組資源的集合。靜態資源分配 這組資源在伺服器啟動之初,就已經被建立並初始化 動態資源分...