从这个版本开始,后面的代码差不多是越来越难啦.
这个版本,我们主要是要实现一个线程池版本的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
析构了,锁就解开了,代码很漂亮.
总结
好了,这个版本的代码就是这样啦,感兴趣的同学可以到这里来查看代码:
https://github.com/lishuhuakai/Spweb