2015-10-14 32 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可以取消()
  • 任何在這個過程中調用線程退出(),
  • 主線程返回, 在這種情況下,進程中的所有線程都會立即終止,
相關問題