好吧.一个mutex 只能解决 一个生产者, 一个消费者的情况;
生产消费 具体是这样的, 2个线程同时启动, 生产线程比如在数组中放入一个值, 然后通知消费线程,消费线程干完事后再通知生产者.
消费者的核心是 俺永远只能跟在生产者屁股后面
使用一个mutex 实现 (当然 只用一个mutex , 只能让线程去抢占了) , 下一个例子是用2个事件对象,
const int BUFF_SIZE = 10; struct { HANDLE mutex; //一个mutex 就能搞定了 int arr[BUFF_SIZE]; int index; //生产者生产的位置 } share_object; unsigned int WINAPI producer_thread( void* lpParameter) { while(1) { WaitForSingleObject(share_object.mutex,-1); if(share_object.index >= BUFF_SIZE){ ReleaseMutex(share_object.mutex); break; } cout << "producer_thread index: " << share_object.index << endl; share_object.arr[share_object.index++] = 1; ReleaseMutex(share_object.mutex); } return 0; } //唯一要注意的是消费者的代码实现 unsigned int WINAPI consumer_thread( void* lpParameter) { for(int i = 0; i < BUFF_SIZE ; ++i) { while(1) { WaitForSingleObject(share_object.mutex,-1); // Sleep(500); 可以打开注释看看具体情况 //如果 i < index 代表生产者在这个位置已经处理完了 if(i < share_object.index){ share_object.arr[i] = 0; cout << "consumer changed :" << i << endl; ReleaseMutex(share_object.mutex); break; } ReleaseMutex(share_object.mutex); } } return 0; } int main(int argc, char *argv[]) { share_object.mutex = CreateMutex(0,FALSE,0); HANDLE handles[2]; handles[0] =(HANDLE) _beginthreadex(0,0,producer_thread,0,0,0); handles[1] = (HANDLE)_beginthreadex(0,0,consumer_thread,0,0,0); WaitForMultipleObjects(2,handles,TRUE,-1); return 0; }
使用事件对象, 也可以使用信号量, 这2个对象可以等待,而不是直接的抢占:
下面的例子中 mutex 完全可以不加. 直接使用2个事件对象 ,来完成;
const int BUFF_SIZE = 10; struct { HANDLE mutex; //可以省略 HANDLE event_empty; //代表生产者可以生产了 HANDLE event_stored; //代表消费者可以消费了 int arr[BUFF_SIZE]; int index; } share_object; unsigned int WINAPI producer_thread( void* lpParameter) { while(1) { WaitForSingleObject(share_object.event_empty,-1); WaitForSingleObject(share_object.mutex,-1); if(share_object.index >= BUFF_SIZE){ ReleaseMutex(share_object.mutex); SetEvent(share_object.event_stored); break; } cout << "producer_thread index: " << share_object.index << endl; share_object.arr[share_object.index++] = 1; ReleaseMutex(share_object.mutex); SetEvent(share_object.event_stored); } return 0; } unsigned int WINAPI consumer_thread( void* lpParameter) { for(int i = 0 ; i< BUFF_SIZE; ++i) { WaitForSingleObject(share_object.event_stored,-1); WaitForSingleObject(share_object.mutex,-1); share_object.arr[i] = 0; cout << "consumer_thread changed:" << i << endl; ReleaseMutex(share_object.mutex); SetEvent(share_object.event_empty); } return 0; } int main(int argc, char *argv[]) { share_object.mutex = CreateMutex(0,FALSE,0); share_object.event_empty = CreateEvent(0,FALSE,TRUE,0); share_object.event_stored = CreateEvent(0,FALSE,FALSE,0); HANDLE handles[2]; handles[0] =(HANDLE) _beginthreadex(0,0,producer_thread,0,0,0); handles[1] = (HANDLE)_beginthreadex(0,0,consumer_thread,0,0,0); WaitForMultipleObjects(2,handles,TRUE,-1); return 0; }
