2014-03-19 60 views
1

我已經編寫了一個解決方案,標準的生產者 - 消費者問題使用一個大小爲5的緩衝區和pthreads與一個空的和完整的信號量和互斥鎖。我認爲一切都按預期工作,但只是注意到我得到堆棧行爲(LIFO)而不是預期的隊列(FIFO)行爲。我已經搜索,但無法找到任何類似的問題,因爲除了訂單以外,我正按預期生產和消費。生產者 - 消費者堆棧行爲,而不是隊列

這是一項家庭作業,所以我沒有真正尋找代碼我只是想知道在哪裏尋找錯誤或知道爲什麼行爲可能會比預期的不同。

struct data 
{ 
pthread_mutex_t mutex; 
sem_t full;    
sem_t empty; 
}; 

int bufferCount;   

buffer_item buffer[BUFFER_SIZE]; 
pthread_t thread; 

int insert_item(buffer_item item) 
{ 
    if (bufferCount < BUFFER_SIZE) 
    { 
    buffer[bufferCount] = item; 
    ++bufferCount; 
    return 0; 
    } 
    else 
    return -1; //insert failed 
} 

int remove_item(buffer_item *item) 
{ 
    if (bufferCount > 0) 
    { 
    *item = buffer[bufferCount - 1]; 
    --bufferCount; 
    return 0; 
    } 
    else 
    return -1; //error failed to remove 

} 

void Initialize (void *param) 
{ 
    struct data *locks = param; 

    pthread_mutex_init(&(locks->mutex), NULL); 
    sem_init(&(locks->full), 0, 0); 
    sem_init(&(locks->empty), 0, BUFFER_SIZE); 
    bufferCount = 0; 

} 

void *producer (void *param) 
{ 
    struct data *locks = param; 
    do 
    { 
    sleep(rand()%5 + 1); //sleep for between 1 and 5 seconds 
    buffer_item num = rand(); 
    sem_wait(&(locks->empty)); 
    pthread_mutex_lock(&(locks->mutex)); 
    if (insert_item(num)) 
    { 
     printf("Insert in producer failed\n"); 
     exit(1); 
    } 
    else 
     printf("Producer produced %d\n", num); 
    pthread_mutex_unlock(&(locks->mutex)); 
    sem_post(&(locks->full)); 
    }while(1); 
} 


void *consumer (void *param) 
{ 
    struct data *locks = param; 
    do 
    { 
    sleep(rand()%5 + 1); //sleep for between 1 and 5 seconds 
    buffer_item num; 
    sem_wait(&(locks->full)); 
    pthread_mutex_lock(&(locks->mutex)); 
    if (remove_item(&num)) 
    { 
     printf("Remove in consumer failed\n"); 
     exit(1); 
    } 
    else 
     printf("Consumer consumed %d\n", num); 
    pthread_mutex_unlock(&(locks->mutex)); 
    sem_post(&(locks->empty)); 
    }while(1); 
} 


int main(int argc, char *argv[]) 
{ 
    if (argc != 4) 
    { 
    printf("Incorrect number of arguments should be 4\n"); 
    exit (1); 
    } 
    int sleepTime = atoi(argv[1]); 
    int producerThreads = atoi(argv[2]); 
    int consumerThreads = atoi(argv[3]); 
    struct data *locks = (struct data *) malloc(sizeof(struct data)); 
    Initialize(locks); 

    for (int i =0; i < producerThreads; ++i) 
    pthread_create(&thread, NULL, producer, locks); 

    for(int i = 0; i < consumerThreads; ++i) 
    pthread_create(&thread, NULL, consumer, locks); 

    sleep(sleepTime); 
    free (locks); 
    return 0; 
} 
+3

錯誤是在第42行 –

+0

有趣.....我確信我可以發佈代碼和數百人可以使它更好,並修復它,但我想從中吸取教訓。因此,一般來說,在生產者消費者問題中,可能會影響消費者從緩衝區中移除的訂單。 – user2514231

+1

你對我們的期望是什麼?如果您編寫的是LIFO而不是FIFO,那麼顯然您的消費者會從容器錯誤的端點消耗掉。但這很明顯,你一定要自己檢查這個 –

回答

1

你的「錯誤」就在這裏:*item = buffer[bufferCount - 1];

當你刪除一個項目,你突然出現在陣列中最遠的,這也是最後插入(因此LIFO行爲)。你需要彈出第一個(和memcpy/index-keeping來移動緩衝區的開始)。

你做什麼:

begin   <-end 
------------------- 
| | | | | | | | |x| 
------------------- 
       | 
       -> *item 

你想做什麼:

begin->   end 
------------------- 
|x| | | | | | | | | 
------------------- 
| 
-> *item 

PS:有性能損失memcpy的緩衝區來重新調整數據數組的開始,這是爲什麼經常使用circular buffers

+0

謝謝....認爲這是我所忽視的只是盯着代碼,沒有看到任何不同的東西導致問題。 – user2514231