2015-10-14 28 views
1

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

我作出改变,以马丁·布罗德赫斯特的源代码(见灰色文本为注释)

/* 
* 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

回答

2

因为C没有对象,没有对象表示线程,因此没有任何设置为NULL的对象。分离的线程在终止时将消失。未连接的线程在连接时会消失。

3

号嗯,这是不是100%清楚Java结构它是你在想的(我敢打赌,有可以调用,而不是将其设置为null,具有GC照顾它的close方法),但这无关紧要,因为......

  1. pthread_t是一个整数(也许)类型,而不是一个指针,所以它不能被设置为NULL。
  2. C是不是垃圾收集,所以即使它是一个指向该线程将无法知道或将其设置为null关怀的方式。
  3. POSIX线程不使用线程池。 pthread_create函数实际上创建了一个全新的OS级线程,并且从处理程序返回实际上会退出它。 (嗯,不是真的。它仍然直到调用pthread_join函数,因为你没有创建为分离线程徘徊。)

什么你应该做的就是创建线程沾边的线程,因为你的现在的代码正在泄漏可连接的线程。

此外,使用& newsock作为参数是危险的,因为它在主循环的每次迭代中被破坏并重新创建。这是一个竞争条件,在笔者的测试可能永远不会出现了,因为在轻负载会等待下一次的主线程接受回报,同时它的工作线程访问,并且在大多数系统相同的空间将被用于在并结束变量。

您可以使用malloc创建一个地方来存储套接字fd(您需要在处理函数结束时释放这个套接字),或者如果您的平台允许这样做(大部分),只需将值到一个指针,然后在处理函数中将其返回。

+0

你说得对。 &newsock是危险的。不仅如此,它只是简单的破碎。它需要修复,但对于这样简单的事情(例如newsock是int),我会(void *)newsock并让线程执行int newsock =(long)ptr而不是去malloc。我只有malloc,如果有一个控制结构正在填充 –

+0

@CraigEstey我推荐malloc,因为我不知道是否能够做到这一点是保证是可移植的 - 你有一个关于往返转换的POSIX参考整数指针和返回? – Random832

+0

即使对于使用LP32/LLP64型号的braindamaged MS编译器,它也会一直有效。所有Unix系统都使用LP32/LP64。对于32位,这是没有意义的。以下是参考/标准,在90年代正式推出http://www.unix.org/version2/whatsnew/lp64_wp.html它甚至可以用于LLP64,因为我们只需要低32位。为简洁起见,我可以完成int newsock =(int)ptr;而且,我是一个参考,因为我已经做了这么多次30多年。你总是可以伪装一个指针内的int - 查看表格 –

0

你有一个的pthread_t为线程ID,没有对象,而且它不会在路上像Java GC的工作。

线程终止在1以下情况:

  • 它的启动函数返回,
  • 线程调用了pthread_exit()
  • 通过pthread_cancel可以取消()
  • 任何在这个过程中调用线程退出(),
  • 主线程返回, 在这种情况下,进程中的所有线程都会立即终止,
相关问题