c - C : do we need to set unused thread to NULL? 中的多线程

标签 c multithreading

这是 C 中的线程服务器代码。我的问题是:我们是否需要将未使用的线程设置为 NULL?在java中,我们需要将thread设置为NULL,让它返回线程池。

我对 Martin Broadhurst 的源代码进行了更改(请参阅灰色文本作为评论)

 /* 
 *  A threaded server
 *  by Martin Broadhurst (www.martinbroadhurst.com)
 *  Compile with -pthread
 */

#include <stdio.h>
#include <string.h> /* memset() */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <pthread.h>

#define PORT    "32001" /* Port to listen on */
#define BACKLOG     10  /* Passed to listen() */

void *handle(void *pnewsock)
{
    /* send(), recv(), close() */

    return NULL;
}

int main(void)
{
    int sock;
    pthread_t thread;
    struct addrinfo hints, *res;
    int reuseaddr = 1; /* True */

    /* Get the address info */
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    if (getaddrinfo(NULL, PORT, &hints, &res) != 0) {
        perror("getaddrinfo");
        return 1;
    }

    /* Create the socket */
    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    if (sock == -1) {
        perror("socket");
        return 1;
    }

    /* Enable the socket to reuse the address */
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1) {
        perror("setsockopt");
        return 1;
    }

    /* Bind to the address */
    if (bind(sock, res->ai_addr, res->ai_addrlen) == -1) {
        perror("bind");
        return 0;
    }

    freeaddrinfo(res);

    /* Listen */
    if (listen(sock, BACKLOG) == -1) {
        perror("listen");
        return 0;
    }

    /* Main loop */
    while (1) {             
        pthread_attr_t *attr;  //<===I added this
        size_t size = sizeof(struct sockaddr_in);
        struct sockaddr_in their_addr;
        int * ptr;   //<===I added this
        ptr = malloc(sizeof(int));       //<===I added this
        ptr = accept(sock, (struct sockaddr*)&their_addr, &size);
        if (newsock == -1) {
            perror("accept");
        }
        else {
               printf("Got a connection from %s on port %d\n",
                inet_ntoa(their_addr.sin_addr), htons(their_addr.sin_port));  
                //I added the following "if" statement
                if (pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED) != 0){
                    fprintf(stderr, "Failed to set thread detached\n");
                }
                else {
                    //if (pthread_create(&thread, NULL, handle, &newsock) != 0) {
                    if (pthread_create(&thread, attr, handle, ptr) != 0 ) {
                        fprintf(stderr, "Failed to create thread\n");
                     }
                }

        }
    }

    close(sock);

    return 0;
}

==========-============== 代码来自这里: http://martinbroadhurst.com/source/threaded-server.c.html

最佳答案

没有。好吧,你不是 100% 清楚你在想什么 Java 构造(我敢打赌你可以调用一个 close 方法而不是将它设置为 null 并让 GC 处理它),但这无关紧要,因为......

  1. pthread_t 是整数(可能)类型,不是指针,因此不能设置为 NULL。
  2. C 不会被垃圾回收,因此即使它是一个指针,线程也无法知道或关心您将它设置为 null。
  3. POSIX 线程不使用线程池。 pthread_create 函数实际上创建了一个全新的操作系统级线程,从处理程序返回实际上退出了它。 (好吧,不是真的。在您调用 pthread_join 之前它仍然存在,因为您没有将它创建为分离线程。)

应该做的是将线程创建为分离线程,因为您的代码现在正在泄漏可连接线程。

此外,使用 &newsock 作为参数是危险的,因为它在主循环的每次迭代中都会被销毁并重新创建。这是一个可能从未出现在作者测试中的竞争条件,因为在轻负载下,主线程将等待下一个 accept 返回,同时在工作线程上访问它,并且在大多数系统上将使用相同的空间并结束变量。

您可以使用 malloc 创建一个存储套接字 fd 的位置(您需要在处理程序函数结束时释放它),或者,如果您的平台允许这样做(大多数情况下允许),只需将值转换为一个指针,然后在处理程序函数中将其投回。

关于c - C : do we need to set unused thread to NULL? 中的多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33116110/

相关文章:

c - C中的指针存储

c - 应用程序的稳健正常关闭

multithreading - 多线程访问(读/写)同一个表

无法在 MAC 终端上执行二进制文件

c - 在 C 中返回 char* 的 x86 函数

python - word2vec tensorflow 中的执行流程

c# - 使用 NHibernate 重用线程的 session

java - 使用连接池后仍然出现 You can't run on a Closed ResultSet 错误

linux - 如果在 Linux 中尝试两次锁定同一个互斥量,为什么线程不会死锁?

c - 使用 OpenSSL API 以编程方式验证证书链