zoukankan      html  css  js  c++  java
  • TCP并发服务器(六)——创建线程池,每个线程accept,accept使用互斥锁保护——基于UNP代码

    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
    ", tcnt);
    
        void web_child(int);
        struct sockaddr *cliaddr = (struct sockaddr*)Malloc(addrlen);
        
        //accept,然后处理连接
        for (;;) {
            socklen_t clilen = addrlen;
    
            DPRINTF("thread %d lock
    ", tcnt);
             //加锁
            Pthread_mutex_lock(&mlock);
            DPRINTF("thread %d start to accept
    ", tcnt);
            int connfd = Accept(listenfd, cliaddr, &clilen);
            DPRINTF("thread %d accept a connection
    ", tcnt);
            Pthread_mutex_unlock(&mlock);
            DPRINTF("thread %d unlock
    ", tcnt);
    
            ++tptr[tcnt].thread_count;
            DPRINTF("thread %d accept %d connections
    ", 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;
    }
  • 相关阅读:
    接口自动化架构-获取用例
    Windows性能监控工具Perfmon使用指南
    接口自动化架构1-setting
    多进程
    线程锁、守护线程
    多线程
    xlrd模块
    封装写日志的类
    封装redis
    继承
  • 原文地址:https://www.cnblogs.com/hancm/p/3858753.html
Copyright © 2011-2022 走看看