Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 服务器中的Leader/Follower pthread实现_C_Multithreading_Concurrency_Pthreads - Fatal编程技术网

C 服务器中的Leader/Follower pthread实现

C 服务器中的Leader/Follower pthread实现,c,multithreading,concurrency,pthreads,C,Multithreading,Concurrency,Pthreads,我正在尝试实现一个基于leader/follower并发体系结构的基本服务器。 我最初只是想创建一个线程池并创建一个线程队列,但在阅读了这个答案()之后,我觉得我的算法是不正确的,因为选择的答案声称互斥是不必要的 leader/follower背后的思想是初始化一个线程池,其中一个线程充当“leader”线程,其余的则是“follower”线程。在服务器中,主线程将侦听传入的连接,而从线程将全部侦听其余的连接。当引导线程检测到传入连接时,其中一个静止的跟随线程将被提升到新的引导线程中,而前引导线

我正在尝试实现一个基于leader/follower并发体系结构的基本服务器。 我最初只是想创建一个线程池并创建一个线程队列,但在阅读了这个答案()之后,我觉得我的算法是不正确的,因为选择的答案声称互斥是不必要的

leader/follower背后的思想是初始化一个线程池,其中一个线程充当“leader”线程,其余的则是“follower”线程。在服务器中,主线程将侦听传入的连接,而从线程将全部侦听其余的连接。当引导线程检测到传入连接时,其中一个静止的跟随线程将被提升到新的引导线程中,而前引导线程接受连接并服务于请求。当前引导线程完成服务请求时,它将成为静止的跟随线程

但是,如果不使用互斥体和条件变量,我看不到任何实现方法。目前,我的实现使用一个线程池,只允许每个线程接受互斥体中的新连接

有人能提供一个高层的领导者/追随者实施的解释吗

下面是我为当前实现编写的一些代码

#define THREAD_COUNT 10
pthread_mutex_t request_tx;

int main(int argc, char* argv[])
{
    pthread_t threadA[THREAD_COUNT];
    pthread_mutex_init(&request_tx, NULL);

    //initialize server socket stuff

    for (int i = 0; i < THREAD_COUNT; ++i)
    {
        pthread_create(&threadA[i], NULL, rest, NULL);
    }

    for (int i = 0; i < THREAD_COUNT; ++i)
        pthread_join(threadA[i], NULL);

    return 0;
}

void* rest(void* kargs)
{
    int client_fd;
    struct sockaddr_in cli_addr;
    socklen_t sin_t = sizeof(cli_addr);
    while (1)
    {
        pthread_mutex_lock(&request_tx);
        client_fd = accept(server_fd, (struct sockaddr*) &cli_addr, &sin_t);
        if (client_fd > 0)
            serve(client_fd);
        else
            pthread_mutex_unlock(&request_tx);
    }
}

void serve(int client_fd)
{
    pthread_mutex_unlock(&request_tx);
    // serve request here
    ...
}
#定义线程计数10
pthread_mutex_t request_tx;
int main(int argc,char*argv[])
{
pthread_t threadA[线程计数];
pthread_mutex_init(&request_tx,NULL);
//初始化服务器套接字
对于(int i=0;i0)
服务(客户服务部);
其他的
pthread_mutex_unlock(&request_tx);
}
}
无效发球(int客户端\U fd)
{
pthread_mutex_unlock(&request_tx);
//在这里提出要求
...
}

链接的答案是错误的。在某些地方同步是绝对必要的。在您的示例中,您可以删除互斥锁,因为
accept
将在内核中阻塞,并且(大多数?)实现将为传入连接激活一个线程。但是,内核中仍然存在一些同步

您的示例有点误导,因为leader/followers模式通常用于将多个连接上的单个请求分发到线程池,而不是连接。在这一点上,事情变得相当复杂,因为已经完成处理的跟随者需要告诉领导者需要观察新的连接。如果您仅限于标准POSIX接口,那么这可能会涉及到很多问题。(使用
epoll
,应该可以将大部分复杂性转移到内核。)


一般来说,我会谨慎地采用90年代的事件处理模式。自那时以来,体系结构发生了重大变化:NUMA机器不再罕见,系统可以在一个进程中轻松处理成千上万个线程,并且可以使用其他事件处理接口,如
epoll

链接的答案是错误的。在某些地方同步是绝对必要的。在您的示例中,您可以删除互斥锁,因为
accept
将在内核中阻塞,并且(大多数?)实现将为传入连接激活一个线程。但是,内核中仍然存在一些同步

您的示例有点误导,因为leader/followers模式通常用于将多个连接上的单个请求分发到线程池,而不是连接。在这一点上,事情变得相当复杂,因为已经完成处理的跟随者需要告诉领导者需要观察新的连接。如果您仅限于标准POSIX接口,那么这可能会涉及到很多问题。(使用
epoll
,应该可以将大部分复杂性转移到内核。)


一般来说,我会谨慎地采用90年代的事件处理模式。自那时以来,体系结构发生了重大变化:NUMA机器不再罕见,系统可以在一个进程中轻松处理成千上万个线程,并且可以使用其他事件处理接口,如
epoll

您还没有接近创建MCVE(),虽然您添加了一些代码,我正要说“您没有提供任何代码”。显示的片段中的互斥锁存在解锁问题。除非存在
pthread\u mutex\u锁(&request\u tx)
在函数的每个路径之前的
service()
末尾,最后的
pthread\u mutex\u unlock(&request\u tx)rest()
中的code>解锁已解锁的互斥锁,除非
client\u fd
为零或负(在这种情况下,不调用
service()
)。这并不能激发信心,部分原因是即使我解决了锁的问题,我也不知道这是否是实现架构的正确方法。你能在更高的层次上解释一下这个实现吗?我将编辑更多的代码来显示线程池初始化,但这并没有什么特别之处。我在“不清楚你在问什么”、“太宽泛”和“MCVE”之间进行了辩论,认为这是最接近的原因。我不清楚
service()
做什么;我不清楚
rest()
做了什么-它看起来可能是
pthread\u create()
的线程函数。我不确定线程池在哪里。交叉引用的问题有一个选定的答案,声称“无需同步”,但