TCP并发服务器(六)——创建线程池,每个线程accept,accept使用互斥锁保护——基于UNP代码
2014-07-21 16:49
761 查看
TCP并发服务器(六)——创建线程池,每个线程accept,accept使用互斥锁保护——基于UNP代码
1.说明
预创建一个线程池,线程池中各个线程accept。主线程不做什么。
这是Leader/Follower领导者/跟随者模式
2.代码
代码基于UNP的库函数
我们没有让线程阻塞于accept, 而是选择了互斥锁保证只有一个线程再接收。
我们没有理由使用文件锁,因为对于进程中的各个线程,总可以使用互斥锁,而且性能更好。
在源自BSD的内核中,我们可以不为accept上锁。使得用户CPU时间减少,但是系统CPU时间会增加。
原因是因为多个线程被唤醒引发惊群。总的时间会增加。
由于把每个连接派遣到线程池中某个线程需要互斥,因此让内核派遣不如通过线程函数库派遣快。
这个版本是当前版本中最快的。
1.说明
预创建一个线程池,线程池中各个线程accept。主线程不做什么。
这是Leader/Follower领导者/跟随者模式
2.代码
代码基于UNP的库函数
我们没有让线程阻塞于accept, 而是选择了互斥锁保证只有一个线程再接收。
我们没有理由使用文件锁,因为对于进程中的各个线程,总可以使用互斥锁,而且性能更好。
在源自BSD的内核中,我们可以不为accept上锁。使得用户CPU时间减少,但是系统CPU时间会增加。
原因是因为多个线程被唤醒引发惊群。总的时间会增加。
由于把每个连接派遣到线程池中某个线程需要互斥,因此让内核派遣不如通过线程函数库派遣快。
这个版本是当前版本中最快的。
#include "unpthread.h" //线程信息 typedef struct { pthread_t thread_tid; //thread ID long thread_count; //connections handled } Thread; //线程结构数组 Thread *tptr; //array of Thread structures; calloc'ed int listenfd, nthreads; socklen_t addrlen; pthread_mutex_t mlock = PTHREAD_MUTEX_INITIALIZER; static void thread_make(int i); static void sig_int(int signo) { void pr_cpu_time(void); pr_cpu_time(); exit(0); } int main(int argc, char *argv[]) { if (argc == 3) { listenfd = Tcp_listen(NULL, argv[1], &addrlen); } else if (argc == 4) { listenfd = Tcp_listen(argv[1], argv[2], &addrlen); } else { err_quit("Usage: a.out [ <host> ] <port#> <#threads>"); } nthreads = atoi(argv[argc - 1]); tptr = (Thread*)Calloc(nthreads, sizeof(Thread)); //预创建一定数目线程 for (int i = 0; i < nthreads; ++i) { thread_make(i); } Signal(SIGINT, sig_int); //主线程什么也不做,创建的各个线程accept for (;;) { pause(); } return 0; } static void *thread_main(void *arg) { //第几个线程 int tcnt = (int)arg; DPRINTF("thread %d starting\n", tcnt); void web_child(int); struct sockaddr *cliaddr = (struct sockaddr*)Malloc(addrlen); //accept,然后处理连接 for (;;) { socklen_t clilen = addrlen; DPRINTF("thread %d lock\n", tcnt); //加锁 Pthread_mutex_lock(&mlock); DPRINTF("thread %d start to accept\n", tcnt); int connfd = Accept(listenfd, cliaddr, &clilen); DPRINTF("thread %d accept a connection\n", tcnt); Pthread_mutex_unlock(&mlock); DPRINTF("thread %d unlock\n", tcnt); ++tptr[tcnt].thread_count; DPRINTF("thread %d accept %d connections\n", tcnt, tptr[tcnt].thread_count); web_child(connfd); Close(connfd); } return NULL; } static void thread_make(int i) { Pthread_create(&tptr[i].thread_tid, NULL, &thread_main, (void*)i); return; }
相关文章推荐
- TCP并发服务器(七)——可动态增减的线程池,主线程accept——基于UNP代码修改
- 多进程并发编程----基于高级的预先创建进程池(accept使用线程上锁)的模型
- TCP并发服务器(四)——预创建子进程,accept互斥锁
- 【Java TCP/IP Socket】基于线程池的TCP服务器(含代码)
- 使用 线程池,控制线程 , 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待:
- 【Java TCP/IP Socket】基于线程池的TCP服务器(含代码)
- TCP并发服务器(二)——预创建子进程,accept不上锁
- 多进程并发编程----基于高级的预先创建进程池(accept使用文件上锁)的模型
- Linux TCP 服务器编程(六):基于线程的并发服务器
- TCP并发服务器(三)——预创建子进程,accept文件锁
- TCP并发服务器(五)——每个客户一个线程
- UNIX网络编程卷1 服务器程序设计范式6 并发服务器,为每个客户请求创建一个线程
- (UNP点滴记录) TCP端口号与并发服务器,缓冲区大小限制,TCP/UDP输出机制
- TCP服务器设计范式 - 每个客户连接对应一个线程
- 基于线程池,封装的TCP服务器框架
- Delphi XE2 编写的----基于消息的单线程TCP服务器
- 什么时候手动创建线程而不使用线程池
- 实战:使用TCP/IP筛选保护服务器安全
- 线程创建, 使用, 释放代码
- 服务器编程入门(11)TCP并发回射服务器实现 - 单线程select实现