一起來寫web server 04 -- 執行緒池版本
阿新 • • 發佈:2019-02-01
從這個版本開始,後面的程式碼差不多是越來越難啦.
這個版本,我們主要是要實現一個執行緒池版本的web server
.這個版本的設計出自UNP
.
思想
思想非常簡單,那就是父執行緒首先構建n
多子執行緒,這些子執行緒全部爭搶全域性的一把鎖,只有搶到了鎖的執行緒才能夠呼叫accept
函式,否則都會阻塞掉.
程式碼
/*-
* 執行緒池版本的web server.主要的思想是事先構建一個執行緒池,只是需要注意的是,accept的時候需要加鎖.
*/
int listenfd; /* 全域性的一個監聽套接字 */
MutexLock mutex; /* 全域性的一把鎖 */
int main(int argc, char *argv[])
{
listenfd = Open_listenfd(8080); /* 8080號埠監聽 */
//signal(SIGPIPE, SIG_IGN);
pthread_t tids[10];
void* thread_main(void *);
for (int i = 0; i < 10; ++i) {
int *arg = (int *)Malloc(sizeof(int)); /* 這個東西不會共享 */
*arg = i;
Pthread_create(&tids[i], NULL, thread_main, (void *)arg);
}
for ( ; ; )
pause();
return 0;
}
void* thread_main(void *arg)
{
printf("thread %d starting\n", *(int*)arg);
Free(arg);
struct sockaddr cliaddr;
socklen_t clilen;
int connfd;
while (true) {
{
MutexLockGuard lock(mutex); /* 加鎖 */
connfd = Accept(listenfd, &cliaddr, &clilen);
}
doit(connfd); /* 處理連線 */
close(connfd); /* 關閉連線 */
}
}
鎖
一般涉及到多執行緒的資源共享,鎖或者說互斥,加上一個同步機制,總是逃不開的話題.
對於共享資源的寫,總是要加鎖的.如何來構造一把鎖呢?我這裡的程式碼參考了muduo
庫的設計.
我們一起來看一下MutexLock
這個類.
class MutexLock : noncopyable
{
private:
pthread_mutex_t mutex_; /* 這是系統定義的鎖的型別 */
pid_t holder_; /* 記錄擁有執行緒的id */
...
}
它的建構函式,僅僅是呼叫普通的鎖的初始化的程式碼:
MutexLock()
: holder_(0)
{
pthread_mutex_init(&mutex_, NULL); /* 初始化 */
}
它的解構函式,主要是呼叫鎖的銷燬函式.
~MutexLock()
{
assert(holder_ == 0);
pthread_mutex_destroy(&mutex_); /* 銷燬鎖 */
}
MutexLock
這個類巧妙的利用了CPP
類的特性來管理鎖這個資源.
接下來比較重要的是加鎖以及解鎖操作:
void lock()
{
MCHECK(pthread_mutex_lock(&mutex_));
assignHolder(); /* 指定擁有者 */
}
void unlock()
{
unassignHolder(); /* 丟棄擁有者 */
MCHECK(pthread_mutex_unlock(&mutex_));
}
如何來使用這個鎖呢?muduo
庫設計了另外一個類,叫做MutexLockGuard
.這個類非常簡單:
class MutexLockGuard : noncopyable
{
public:
explicit MutexLockGuard(MutexLock& mutex)
: mutex_(mutex)
{
mutex_.lock(); /* 構造時加鎖 */
}
~MutexLockGuard()
{
mutex_.unlock(); /* 析構時解鎖 */
}
private:
MutexLock& mutex_; /* 持有鎖的一個引用 */
};
通過這個類,我們就可以很方便的實現加鎖和解鎖操作了,我們只需要向之前程式碼裡那樣使用就行了:
{
MutexLockGuard lock(mutex); /* 加鎖 */
...do other thing...
}
在這個中括號包圍的作用域裡,鎖是有效的,出了這個作用域,lock
析構了,鎖就解開了,程式碼很漂亮.