從執行緒視角看生產者消費者模型

2021-08-19 09:51:31 字數 3736 閱讀 3839

生產者消費者模型

通常說到生產者消費者模型,就會想到:「3種關係,2個角色,1個交易場所」

3種關係:

1、生產者與生產者之間:互斥

2、消費者與消費者之間:互斥

3、生產者與消費者之間:互斥且同步

2個角色:

生產者與消費者

1個交易場所:

臨界區

下面寫乙個基於鍊錶的生產者消費者例子:

#include

#include

#include

#include

struct msg

;struct msg *head = null;

pthread_cond_t cond;

pthread_mutex_t mutex;

pthread_t threads[4];

void *consumer(void *p)

printf("%d end wait a condition...\n",num);

printf("%d begin consume product...\n",num);

mp = head;

head = mp->next;

pthread_mutex_unlock(&mutex);

printf("consume %d\n",mp->num);

free(mp);

printf("%d end consume product...\n\n",num);

sleep(rand()%5);

}}void *producer(void *p)

}int main()

//建立兩個執行緒模擬生產者

//2和3是生產者

for(i = 0;i < 2;i++)

//等待執行緒結束

for(i = 0;i < 2+2;i++)

//銷毀互斥量和條件變數

pthread_mutex_destroy(&mutex);

pthread_cond_destroy(&cond);

return

0;}

執行結果如下:

posix訊號量

在這之前,我們在介紹程序間通訊方式時也提到乙個訊號量,那是system v 版本的訊號量,今天我們來看一下posix訊號量。

明確一點,posix訊號量與system v版本的訊號量的作用是相同的,都是用於同步操作,達到無衝突的訪問共享資源的目的,但不同的是,posix訊號量(無命名的訊號量)可用於執行緒間同步,而system v版本的訊號量是用於程序間的同步(有命名的posix訊號量一般用於程序間同步)。

我們在來看看乙個基於環形佇列的生產者消費者模型的例子:

//這裡修改了之前的佇列的兩個函式**,其中注釋掉的部分就是本次使用的函式中不需要的部分

//入佇列操作函式

void queuepush(queue *queue,datatype value)

// if(queue->size >= max_size)

//

queue->data[queue->tail++] = value;

queue->size++;

if(queue->size == max_size)

if(queue->tail > max_size)

}//取隊首元素函式

int queuegettop(queue *queue,datatype *value)

// if(queue->size == 0)

//

*value = queue->data[queue->head];

return1;}

//以下是模基於環形佇列擬生產者消費者的相關**

從圖中我們可以看到,生產者生產了好幾個資料之後消費者才消費乙個,但是消費這第一次消費的並不是生產者生產的第乙個資料,因為生產者生產大資料的速度遠超消費者的消費資料的速度,還沒有被消費就被新生產的資料覆蓋了。換句話說,消費者和生產者之間沒有同步。

下面我們使用posix訊號量來實現兩者之間的同步:

相關介面:

初始化訊號量

#include

intsem_init(sem_t *sem,int pshared,unsigned

int value);

//引數pshared:0表示執行緒間共享,非0表示程序間共享

//value:訊號量初始值

銷毀訊號量:

int sem_destroy(sem_t *sem);
等待訊號量:

//等待訊號量,會將訊號量的值-1

int sem_wait(sem_t *sem);

發布訊號量:

//發布訊號量,表示資源使用完畢,可以歸還資源了,將訊號量值加1

int sem_post(sem_t *sem);

pthread_mutex_t mutex;

sem_t pro;

sem_t con;

void

*consumer(void

*arg)

else

}}void

*producer(void

*arg)

}int main()

測試結果如下:

至此我們看到生產者與消費者之間實現了同步,即生產者生產了乙個資料,消費者消費乙個。儘管二者速度不一樣,但是通過訊號量依然能夠實現二者之間的同步。

通俗說明:生產者生產乙個資料,傳送訊號告訴消費者可以來消費,消費者消費完資料以後,傳送訊號給生產者,意為資料我已經消費完了,你可以繼續生產了

執行緒,生產者消費者模型

什麼是執行緒 1.執行緒是cpu最小的執行單位 2.程序是資源單位 3.如果將作業系統比作工廠的話,程序是車間,執行緒是流水線,而cpu為電源 開啟乙個程序預設有乙個執行緒即主線程 執行緒的兩種開啟方式 例項化thread類 自定義mythread類,繼承thread類,覆蓋run方法 什麼時候需要...

生產者消費者模型

1.生產者消費者問題 producer consumer 有限緩衝,多執行緒同步。生產者執行緒和消費者執行緒共享固定大小緩衝區。2.關鍵是保證生產者不會再緩衝區滿時加入資料,消費者不會在緩衝區空時消耗資料。3.解決辦法 讓生產者在緩衝區滿時休眠,等下次消費者消耗緩衝區中的資料的時候,生產者才能被喚醒...

生產者消費者模型

生產者與消費者 3,2,1 三種關係 生產者與消費者 互斥,同步 消費者與消費者 互斥 生產者與生產者 互斥 條件變數 int pthread cond destroy pthread cond t cond int pthread cond init pthread cond t restrict...