簡體   English   中英

多線程,消費者和生產者

[英]Multi-threading, consumers and producers

由於我是本主題的新手,因此我在多線程方面遇到問題。 下面的代碼是我從大學獲得的代碼。 它只有幾個版本,而我大部分都了解。 但是我不太了解nready.nready變量以及所有這些線程條件。 誰能描述這兩個在這里的工作方式? 為什么我不能僅通過互斥量同步線程的工作?

#include    "unpipc.h"

#define MAXNITEMS       1000000
#define MAXNTHREADS         100

    /* globals shared by threads */
int     nitems;             /* read-only by producer and consumer */
int     buff[MAXNITEMS];

struct {
pthread_mutex_t mutex;
pthread_cond_t  cond;
int             nput;
int             nval;
int             nready;
} nready = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER };

void    *produce(void *), *consume(void *);

/* include main */
int
main(int argc, char **argv)
{
int         i, nthreads, count[MAXNTHREADS];
pthread_t   tid_produce[MAXNTHREADS], tid_consume;

if (argc != 3)
    err_quit("usage: prodcons5 <#items> <#threads>");
nitems = min(atoi(argv[1]), MAXNITEMS);
nthreads = min(atoi(argv[2]), MAXNTHREADS);

Set_concurrency(nthreads + 1);
    /* 4create all producers and one consumer */
for (i = 0; i < nthreads; i++) {
    count[i] = 0;
    Pthread_create(&tid_produce[i], NULL, produce, &count[i]);
}
Pthread_create(&tid_consume, NULL, consume, NULL);

    /* wait for all producers and the consumer */
for (i = 0; i < nthreads; i++) {
    Pthread_join(tid_produce[i], NULL);
    printf("count[%d] = %d\n", i, count[i]);    
}
Pthread_join(tid_consume, NULL);

exit(0);
}
/* end main */

void *
produce(void *arg)
{
    for ( ; ; ) {
    Pthread_mutex_lock(&nready.mutex);
    if (nready.nput >= nitems) {
        Pthread_mutex_unlock(&nready.mutex);
        return(NULL);       /* array is full, we're done */
    }
    buff[nready.nput] = nready.nval;
    nready.nput++;
    nready.nval++;
    nready.nready++;
    Pthread_cond_signal(&nready.cond);
    Pthread_mutex_unlock(&nready.mutex);
    *((int *) arg) += 1;
}
}

/* include consume */
void *
consume(void *arg)
{
int     i;

for (i = 0; i < nitems; i++) {
    Pthread_mutex_lock(&nready.mutex);
    while (nready.nready == 0)
        Pthread_cond_wait(&nready.cond, &nready.mutex);
    nready.nready--;
    Pthread_mutex_unlock(&nready.mutex);

    if (buff[i] != i)
        printf("buff[%d] = %d\n", i, buff[i]);
}
return(NULL);
}
/* end consume */
pthread_mutex_lock(&nready.mutex);
while (nready.nready == 0)
    pthread_cond_wait(&nready.cond, &nready.mutex);
nready.nready--;
pthread_mutex_unlock(&nready.mutex);

該結構的全部目的是確保在執行相應的動作(nready.nready--)時條件(nready.nready == 0)仍然為true,或者-如果不滿足條件-等待直到它滿足無需占用CPU時間。

您只能使用互斥鎖,以檢查條件是否正確並自動執行相應的操作。 但是,如果條件不滿足,您將不知道該怎么辦。 等待? 到什么時候? 再檢查一次? 釋放互斥並在之后立即重新檢查? 那會浪費CPU時間...

pthread_cond_signal()和pthread_cond_wait()可以解決此問題。 您應該檢查他們的手冊頁。

簡而言之,pthread_cond_wait的作用是使調用線程進入休眠狀態,並以原子方式釋放互斥鎖,直到發出信號為止。 因此,這是一個阻止功能。 然后可以通過調用信號或從其他線程廣播來重新安排線程。 當線程發出信號時,它將再次獲取互斥量並退出wait()函數。

到目前為止,您知道

  1. 你的情況是真實的,
  2. 您持有互斥量。

因此,您可以做任何需要處理的數據。

但是要小心,如果您不確定另一個線程是否會發出信號,則不應調用wait。 這是死鎖的一個非常常見的來源。

當線程接收到信號時,它將被放入准備進行調度的線程列表中。 在實際執行線程時,您的條件(即nread.nready == 0)可能再次為假。 因此是while(以重新檢查線程是否被喚醒)。

"But I don't really understand the nready.nready variable"

this results from the struct instance being named 'nready' and there 
is a field within the struct named 'nready'

IMO: a very poor design to have two different objects being given the same name

the nready field of the nready struct seems to be keeping track of the number of 
items that have been 'produced'

1) nready日提交的struct nready用於粘性多少任務准備消耗,即在陣列的其余任務buff nready.nready++; 僅當生產者將一個新項目放入數組buffnready.nready--;時才執行該nready.nready--; 僅當消耗使物品失去buff時執行。 使用is變量,程序員可以始終跟蹤要處理的任務數量。

2)

pthread_mutex_lock(&nready.mutex);
while (nready.nready == 0)
    pthread_cond_wait(&nready.cond, &nready.mutex);
nready.nready--;
pthread_mutex_unlock(&nready.mutex);

上面的語句是常見條件變量的用法。 您可以檢查POSIX線程編程條件變量,以獲取有關條件變量的更多信息。

為什么不能只使用互斥鎖? 您可以一次又一次輪詢互斥鎖。 顯然,這很浪費CPU時間,並且可能會嚴重影響系統性能。 相反,您希望消耗者在buff沒有更多物品時在睡眠中等待,並在生產者將新物品放入buff時喚醒。 條件變量在此充當此角色。 當沒有任何項時(nready.nready == 0), pthread_cond_wait()函數將當前線程置於睡眠狀態,從而節省了寶貴的CPU時間。 當有新商品到達時, Pthread_cond_signal()喚醒消費者。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM