2013-02-26 91 views
1

我想編程一個Web服務器,使用線程池,其中主線程需要一個連接,將它傳遞給線程,並且線程處理它。不能共享pthread之間的變量,值是不同的

我必須爲每個線程結構和工作隊列追究他們

struct worker { 
    pthread_t* thread; 
    struct queue* workerQueue; 
    char* busy; 
    int connfd; 
    int id; 
}; 

struct queue { 
    int start; 
    int end; 
    int size; 
    struct worker* workers; 
}; 

主線程設置隊列和線程,並遍歷使用這兩個功能連接

struct queue* workerQueue; 
      workerQueue = (struct queue*) constructQueue(10); 
      int j; 
      int* testParam; 
      //create workers and put in queue 
      for(j=0;j<5;j++) 
      { 
       struct worker* w = &(workerQueue->workers[j]); 
       w = (struct worker*)constructWorker(processConnection,testParam, workerQueue,j); 
       queueAdd(workerQueue,w); 
      } 
connection = accept(fd, (struct sockaddr *) &cliaddr, &cliaddrlen); 
     puts("got connection\n"); 


     w =(struct worker*) queueRemove(workerQueue); 
     //w->connfd = connection; 
     w->busy = "BUSY"; 
     printf("Worker %d has accepted a connection and is %s\n",w->id,w->busy); 

..

struct queue* constructQueue(int numThreads) 
    { 
     struct queue* q = (struct queue *)malloc(sizeof(struct queue)); 
     q->start = 0; 
     q->end = 0; 
     q->workers = (struct worker*)malloc(sizeof(struct worker)*numThreads); 
     q->size = numThreads; 
     return q; 
    } 

struct worker* constructWorker(void* (*function)(void*),void* param, struct queue* wq, int i) 
{ 
    struct worker* w = (struct worker*)malloc(sizeof(struct worker)); 
    w->workerQueue = wq; 
    char * busy = (char*)malloc(10); 
    w->busy= "IDLE"; 
    w->connfd = 0; 
    w->id = i; 
    pthread_t t; 
    w->thread = &t; 
    pthread_create(w->thread,NULL,function,w); 
    return w; 
} 

...和線程使用的函數是

void* processConnection(void* serverThread) 
{ 
     //cast serverthread 
     struct worker* w; 
     char* b; 
     int threadID; 
     w = (struct worker*)serverThread; 
     b = w->busy; 
     threadID = w->id; 


     while (1) 
     { 
      char c[10]; 
      printf("\nbusy: %s, thread: %d\n",b,threadID); 
      gets(c) 

;

我想要發生的事情是:工人被創建,忙於設置爲空閒,並開始忙於等待。那麼在主循環中,接受連接並將其分配給工人,並且工人繁忙值被設置爲繁忙。那麼在processConnections中,如果線程繁忙,它應該實際處理它。問題是,雖然我的隊列包含的指針不是值,但當我更新主線程中的工作人員時,似乎並沒有影響processConnection中工作人員的值。我可以將busy設置爲BUSY,並將它打印在主循環中,但busy的值始終在processConnection中爲IDLE。有任何想法嗎?

+0

如果同時訪問一個變量,訪問它應該使用互斥量進行序列化。對於* pthreads *,可以使用'pthread_mutex_t'類型的變量來完成。請閱讀man pthread_mutex_init。 – alk 2013-02-26 07:20:19

回答

1

您可能未在其他線程中看到更新的值,因爲線程之間沒有同步點。編譯器優化和緩存(in)一致性是發生這種情況的兩個原因。要保持相同的策略,你需要一個記憶障礙。如果使用gcc,最簡單的方法是在讀取共享數據之前和寫入共享數據之前先輸入__sync_synchronize()

你需要修復的另一件事是,當你做

pthread_t t; 
w->thread = &t; 

t內存是易該函數返回後可以重複使用。你不能取得局部變量的地址,並以一種超過函數生命週期的方式存儲它。做正確的事情是有一個pthread_t領域struct worker並通過字段的pthread_create地址:

pthread_create(&w->thread, ...); 
+0

修復了pthread創建問題,歡呼聲。不幸的是syncchronise()什麼也沒做。我也嘗試過投入一些互斥鎖,但它們似乎只是造成了一個死鎖 – James 2013-02-26 06:26:27

1

嘗試改變的busy定義

volatile char * busy; 

這告訴編譯器的價值即使代碼沒有明確地訪問該變量,該變量也可以在代碼運行時更改。

但是,您還有很多其他問題。例如,

char * busy = (char*)malloc(10); 
w->busy= "IDLE"; 

將泄漏由malloc分配的內存。 不要嘗試使用字符串來跟蹤狀態。改爲定義enum {IDLE, BUSY},並將busy定義爲該類型的變量。

+0

Nothing :(儘管如此,謝謝。我意識到內存泄漏,但它的副作用是讓這個該死的東西工作... – James 2013-02-26 06:25:39

+1

'volatile'是並不意味着被用來串行訪問在不同線程之間併發使用的變量,使用一個互斥對象 – alk 2013-02-26 07:24:13

+0

不僅泄漏,而且malloc也不做任何事情,busy和w-> busy是完全兩個不同的位置,即使它們是「IDLE」,它也是一個靜態字符串,它被分配給malloc'ed的存儲根本不會被寫入。 – 2016-01-20 20:32:36

0

我建議增加2個互斥一個在工人,一個在隊列

struct worker { 
     pthread_t* thread; 
     struct queue* workerQueue; 
     mutex_t QueueMutex; 
     char* busy; 
     int connfd; 
     int id; 
     };` 

    struct queue { 
     int start; 
     int end; 
     int size; 
     mutex_t workermutex; 
     struct worker* workers; 
    }; 

您的代碼應該像下面

當你創建一個新的socket,對workermutex一個鎖,然後分配連接

工作線程每次鎖定QueueMutex並添加/刪除隊列中的數據以進行處理。

相關問題