問題描述
生產者消費者問題(英語:Producer-consumer problem),也稱有限緩沖問題(英語:Bounded-buffer problem),是一個多行程同步問題的經典案例, 該問題描述了共享固定大小緩沖區的兩個行程——即所謂的“生產者”和“消費者”——在實際運行時會發生的問題,生產者的主要作用是生成一定量的資料 放到緩沖區中,然后重復此程序,與此同時,消費者也在緩沖區消耗這些資料,該問題的關鍵就是要保證生產者不會在緩沖區滿時加入資料,消費者也不會在緩沖區中空時消耗資料,
要解決該問題,就必須讓生產者在緩沖區滿時休眠(要么干脆就放棄資料),等到下次消費者消耗緩沖區中的資料的時候,生產者才能被喚醒,開始往緩沖區添加資料,同樣,也可以讓消費者在緩沖區空時進入休眠,等到生產者往緩沖區添加資料之后,再喚醒消費者,通常采用行程間通信的方法解決該問題,常用的方法有信號燈法等,如果解決方法不夠完善,則容易出現死鎖的情況,出現死鎖時,兩個執行緒都會陷入休眠,等待對方喚醒自己,該問題也能被推廣到多個生產者和消費者的情形,
代碼要求
- 三個執行緒,兩個緩沖區 第一個執行緒往緩沖區a中put,第二個執行緒從緩沖區a中get,然后put到緩沖區b中;第三個執行緒從緩沖區b中get,第一個執行緒相當于純生產者,第三個線程相當于純消費者,第二個執行緒相當于既是生產者又是消費者,
- 用C++類封裝信號量相關的API函式,實作一個名為Semaphore的類,提供兩個成員 函式:p()和v();
Semaphore s(8);
s.p();
s.v();
- 用兩個鎖分別保護head和tail
實作臨界區互斥訪問的方法之一 信號量法
概念上信號量是表示無力資源數量的物體,它是一個與佇列有關的整型變數,實作上,信號量是一種記錄型資料結構,有兩個分量,一個是信號量的值,一個是等待該信號量的行程佇列的頭指標,
實驗代碼
1 #include <windows.h> 2 #include <iostream> 3 4 5 using namespace std; 6 7 8 class Semaphore { 9 private: 10 HANDLE SSemaphore; 11 public: 12 Semaphore(int m, int n) { 13 SSemaphore = CreateSemaphore(NULL, m, n, NULL); //創建信號量 14 } 15 ~Semaphore() { //銷毀信號量 16 CloseHandle(SSemaphore); 17 } 18 void P() { //P操作 19 WaitForSingleObject(SSemaphore, INFINITE); 20 } 21 22 void V() { //V操作 23 ReleaseSemaphore(SSemaphore, 1, NULL); 24 } 25 26 }; 27 28 29 class Buffer { 30 static const int SIZE = 100; 31 private: 32 int cells[SIZE]; 33 int tail; 34 int head; 35 int num; 36 37 Semaphore semaphore_full_cell; //空格子 38 Semaphore semaphore_empty_cell; //滿格子 39 Semaphore mutex; 40 Semaphore mutex_tail;//保護尾部信號量 41 public: 42 Buffer() 43 : num(0), head(0), tail(0), semaphore_full_cell(0, SIZE), 44 semaphore_empty_cell(SIZE, SIZE), mutex(1, 1), mutex_tail(1, 1){} 45 ~Buffer(){} 46 47 bool put(int x) 48 { 49 semaphore_empty_cell.P(); 50 mutex_tail.P(); 51 if (num == SIZE) { 52 return false; 53 } 54 cells[tail] = x; 55 tail = (tail + 1) % SIZE; 56 num++; 57 mutex_tail.V(); 58 semaphore_full_cell.V(); 59 return true; 60 } 61 62 bool get(int& x) 63 { 64 semaphore_full_cell.P(); 65 mutex.P(); 66 if (num == 0) { 67 return false; 68 } 69 x = cells[head]; 70 head = (head + 1) % SIZE; 71 num--; 72 mutex.V(); 73 semaphore_empty_cell.V(); 74 return true; 75 } 76 }; 77 78 79 Buffer a; //a快取區 80 Buffer b; //b快取區 81 82 83 DWORD WINAPI producer(LPVOID) //生產者執行緒 84 { 85 for (int i = 0; i < 200; i++) { 86 bool ok = a.put(i); 87 if (!ok) { 88 cout << GetCurrentThreadId() << " put: " << i << endl; 89 } 90 } 91 return 0; 92 } 93 94 95 DWORD WINAPI consumer(LPVOID) //消費者執行緒 96 { 97 for (int i = 0; i < 200; i++) { 98 int x; 99 bool ok = b.get(x); 100 if (!ok) { 101 cout << GetCurrentThreadId() << " get: " << endl; 102 } 103 } 104 return 0; 105 } 106 107 108 DWORD WINAPI midder(LPVOID) //即是生產者也是消費者執行緒 109 { 110 for (int i = 0; i < 200; i++) { 111 int x; 112 bool ok1 = a.get(x); 113 if (!ok1) { 114 cout << GetCurrentThreadId() << " get: " << endl; 115 } 116 bool ok = b.put(i); 117 if (!ok) { 118 cout << GetCurrentThreadId() << " put: " << i << endl; 119 } 120 121 } 122 return 0; 123 } 124 125 126 int main() 127 { 128 HANDLE thread1 = CreateThread(NULL, 0, producer, 0, 0, NULL); 129 HANDLE thread2 = CreateThread(NULL, 0, midder, 0, 0, NULL); 130 HANDLE thread3 = CreateThread(NULL, 0, consumer, 0, 0, NULL); 131 132 WaitForSingleObject(thread1, INFINITE); 133 WaitForSingleObject(thread2, INFINITE); 134 WaitForSingleObject(thread3, INFINITE); 135 136 return 0; 137 }
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/33465.html
標籤:C++
上一篇:多載矩陣加法運算 代碼參考
下一篇:2020年04月25日個人賽
