您的位置:首页 > 理论基础 > 计算机网络

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时间会增加。

原因是因为多个线程被唤醒引发惊群。总的时间会增加。

由于把每个连接派遣到线程池中某个线程需要互斥,因此让内核派遣不如通过线程函数库派遣快。

这个版本是当前版本中最快的。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐