好吧.一个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;
}