[关闭]
@lishuhuakai 2016-11-03T16:35:23.000000Z 字数 1877 阅读 1443

一起来写web server 04 -- 线程池版本


从这个版本开始,后面的代码差不多是越来越难啦.

这个版本,我们主要是要实现一个线程池版本的web server.这个版本的设计出自UNP.

思想

思想非常简单,那就是父线程首先构建n多子线程,这些子线程全部争抢全局的一把锁,只有抢到了锁的线程才能够调用accept函数,否则都会阻塞掉.

代码

  1. /*-
  2. * 线程池版本的web server.主要的思想是事先构建一个线程池,只是需要注意的是,accept的时候需要加锁.
  3. */
  4. int listenfd; /* 全局的一个监听套接字 */
  5. MutexLock mutex; /* 全局的一把锁 */
  6. int main(int argc, char *argv[])
  7. {
  8. listenfd = Open_listenfd(8080); /* 8080号端口监听 */
  9. //signal(SIGPIPE, SIG_IGN);
  10. pthread_t tids[10];
  11. void* thread_main(void *);
  12. for (int i = 0; i < 10; ++i) {
  13. int *arg = (int *)Malloc(sizeof(int)); /* 这个东西不会共享 */
  14. *arg = i;
  15. Pthread_create(&tids[i], NULL, thread_main, (void *)arg);
  16. }
  17. for ( ; ; )
  18. pause();
  19. return 0;
  20. }
  21. void* thread_main(void *arg)
  22. {
  23. printf("thread %d starting\n", *(int*)arg);
  24. Free(arg);
  25. struct sockaddr cliaddr;
  26. socklen_t clilen;
  27. int connfd;
  28. while (true) {
  29. {
  30. MutexLockGuard lock(mutex); /* 加锁 */
  31. connfd = Accept(listenfd, &cliaddr, &clilen);
  32. }
  33. doit(connfd); /* 处理连接 */
  34. close(connfd); /* 关闭连接 */
  35. }
  36. }

一般涉及到多线程的资源共享,锁或者说互斥,加上一个同步机制,总是逃不开的话题.
对于共享资源的写,总是要加锁的.如何来构造一把锁呢?我这里的代码参考了muduo库的设计.

我们一起来看一下MutexLock这个类.

  1. class MutexLock : noncopyable
  2. {
  3. private:
  4. pthread_mutex_t mutex_; /* 这是系统定义的锁的类型 */
  5. pid_t holder_; /* 记录拥有线程的id */
  6. ...
  7. }

它的构造函数,仅仅是调用普通的锁的初始化的代码:

  1. MutexLock()
  2. : holder_(0)
  3. {
  4. pthread_mutex_init(&mutex_, NULL); /* 初始化 */
  5. }

它的析构函数,主要是调用锁的销毁函数.

  1. ~MutexLock()
  2. {
  3. assert(holder_ == 0);
  4. pthread_mutex_destroy(&mutex_); /* 销毁锁 */
  5. }

MutexLock这个类巧妙的利用了CPP类的特性来管理锁这个资源.
接下来比较重要的是加锁以及解锁操作:

  1. void lock()
  2. {
  3. MCHECK(pthread_mutex_lock(&mutex_));
  4. assignHolder(); /* 指定拥有者 */
  5. }
  6. void unlock()
  7. {
  8. unassignHolder(); /* 丢弃拥有者 */
  9. MCHECK(pthread_mutex_unlock(&mutex_));
  10. }

如何来使用这个锁呢?muduo库设计了另外一个类,叫做MutexLockGuard.这个类非常简单:

  1. class MutexLockGuard : noncopyable
  2. {
  3. public:
  4. explicit MutexLockGuard(MutexLock& mutex)
  5. : mutex_(mutex)
  6. {
  7. mutex_.lock(); /* 构造时加锁 */
  8. }
  9. ~MutexLockGuard()
  10. {
  11. mutex_.unlock(); /* 析构时解锁 */
  12. }
  13. private:
  14. MutexLock& mutex_; /* 持有锁的一个引用 */
  15. };

通过这个类,我们就可以很方便的实现加锁和解锁操作了,我们只需要向之前代码里那样使用就行了:

  1. {
  2. MutexLockGuard lock(mutex); /* 加锁 */
  3. ...do other thing...
  4. }

在这个中括号包围的作用域里,锁是有效的,出了这个作用域,lock析构了,锁就解开了,代码很漂亮.

总结

好了,这个版本的代码就是这样啦,感兴趣的同学可以到这里来查看代码:
https://github.com/lishuhuakai/Spweb

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注