【问题标题】:Multithreaded client server execution don't end sometimes多线程客户端服务器执行有时不会结束
【发布时间】:2018-08-10 18:22:00
【问题描述】:

这是我的服务器代码。执行老板工人。我指定线程工作者的数量。问题是有时它不回复我的客户,而且大多停留在接收状态。有时它会执行,但前提是客户端线程最少。客户端线程有时无法连接。 任何人都可以指出错误。 谢谢。

【问题讨论】:

  • TLDR;你在启动它们后pthread_join()你的线程吗?
  • 不要使用puts()/printf() 来调试程序,尤其是多线程程序,因为stdout 通常是缓冲的。他们也可能在实现内部有锁。您最好使用特定于操作系统的低级直接写入标准错误,例如 POSIX 样式系统上的write( 2, debugString, strlen( debugString );
  • @IharobAlAsimi 是的,我用过。你可以在最后看到
  • 另外,那个代码太复杂了。一件坏事——你的主线程总是假设它可以找到一个空闲线程。没有必要。使用简单的生产者-消费者模式而不是看起来像生产者-消费者-where-the-producer-tries-to-tell-the-consumer-what-to-do 模式,你会做得更好。只需做一些简单的事情,比如将接受的int 套接字值写入管道,让线程从管道中读取int 大小的套接字值,然后传递传入的连接。
  • 我不排除您的代码结构中存在简单的错字。这种怀疑的原因是一行中有两个“隐藏的”花括号。通过自动缩进器/自动格式化程序运行您的代码。首先,它使其可读,例如人她。例如,我不会在当前状态下对其进行详细检查。其次,它确保缩进实际上遵循结构,这有助于发现/避免可疑的错误。顺便说一句:代码中有大量的强制转换,没有一个是绝对必要的。

标签: c multithreading client-server threadpool worker-thread


【解决方案1】:

检查点:

  1. 如何确保“freeThread+1”已为进程做好准备。无需检查,在您的代码中,您只需尝试锁定相应的互斥锁。

    pthread_mutex_lock(&queue_mutex[freeThread+1]);
    
  2. 为什么要连续发送信号?你不需要。一次就够了。此外,为什么你指的是isThreadFree 标志?这不是安全线程。在竞争条件的情况下,它会被错误地引用。我认为您使用 while 来实现此功能,因为您已经遇到过这个问题。

    while(isThreadFree[freeThread+1]==true) {
      pthread_cond_signal(&queue_has_client[freeThread+1]);
    }
    

建议: 我认为您不需要使用多个互斥锁和 cond_signal。相反,您可以为队列clientQueueand cond 仅使用一个互斥锁。

main()函数中:

pthread_mutex_lock(&queue_mutex);
p = enqueue(clientQueue, client_sock);
pthread_mutex_unlock(&queue_mutex);
pthread_cond_signal(&queue_has_client);

worker()函数中:

while (is_empty_queue(clientQueue)) {
  pthread_cond_wait(&queue_has_client,&queue_mutex);
}
dequeue(clientQueue, &helper);
if (!is_empty_queue(clientQueue))
  wake_up_other_thread = true;
pthread_mutex_unlock(&queue_mutex);
if (wake_up_other_thread) // to wake up other threads to serve the enqueued clients
  pthread_cond_signal(&queue_has_client);

【讨论】:

    【解决方案2】:

    正如其他海报所提到的,您的代码过于复杂,无法简单地将接受的套接字传递给工作线程。

    您所需要的只是一个将套接字从主线程传递到任何可用子线程的队列。您没有实现线程安全队列,而是尝试管理每个线程正在执行的操作。

    这是一个非常简单的方法,使用管道作为队列:

    static int socketPipe[ 2 ];
    
    void *child_thread( void *arg );
    {
        while ( 1 ) {
            int mySocket;
            size_t bytesRead = read( socketPipe[ 0 ], &mySocket, sizeof( mySocket ) );
            if ( bytesRead != sizeof( mySocket ) ) {
                // error
            }
            // now handle socket connection in mySocket
        }
        return( NULL );
    }
    
    int main( int argc, char **argv )
    {
        // create socket pipe
        int rc = pipe( socketPipe );
    
        // create threads and listener socket
    
        // handle incoming connections and pass to child threads
        while ( 1 ) {
            int newConn = accept( mainSocket, &peer, &lenPeer )
            if ( incomingConnection != -1 ) {
                ssize_t written =
                    write( socketPipe[ 1 ], &newConn , sizeof( newConn ) );
                // handle errors
            }
        }
    }
    

    这就是将套接字发送到子线程所需要做的几乎所有事情。

    【讨论】:

      猜你喜欢
      • 2014-12-21
      • 2011-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-10
      • 2019-05-17
      • 2015-01-09
      • 1970-01-01
      相关资源
      最近更新 更多