不用信号量实现的生产者,消费者,

liuzu2016 2012-07-09 05:52:56
大家指点一下,有没哟错误,隐患啊

呵呵




#include<deque>
using std::deque;

#include<iostream>
using std::cout;
using std::endl;



int const BUFFER_MAX_SIZE =10;

deque<int>dq(BUFFER_MAX_SIZE); //BUFFER_MAX_SIZE个大小的缓冲区



class CritHelper
{
临界区帮助类 raii
};



class CritHelpIO //std::cout,std::endl; 防止 生产者,消费者以外的线程使用
{

raii;
};



//初始化数据,子线程以外先调用
void InitData()
{
deque<int>::iter =dq.begin();

for(int i=1;(i<=BUFFER_MAX_SIZE )&& (iter!= dq.end()); i++)
{
*iter=0;
}

}


//队列中添加数据
void put(int n)
{
CritHelper ch;

if(dq.size()==BUFFER_MAX_SIZE) //满了
{
while(1){}; //等到有空位

{
CritHelpIO chi;

cout<<"进入的数据位:"<<n<<endl;

}

dq.push_back(n);

}

}


//获取数据
int get()
{

CritHelper ch;

if(dq.empty()) //空
{
while(1){}; //等到有数据

{
CritHelpIO chi;

cout<<"取出的数据位:"<<dq.front()<<endl;

}

dq.pop_front();

}

}


void Produce(int n)
{
for( int i=0 ;i<n ; i++)
{
put(i);
}
}




void Consumer(int n)
{
for( int i=0 ;i<n ; i++)
{
get();

}

}


...全文
170 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
modicum_lf 2012-07-11
  • 打赏
  • 举报
回复

while(1)确实用错了。
liuzu2016 2012-07-10
  • 打赏
  • 举报
回复
今早看了会资料,发现错误很多

1 一般是用 信号量,之所以用信号量,原因:可以使多个线程同时访问 同一资源

比如 8个生产者线程(缓冲区大小为5,,循环队列作为缓冲区,可以用数组实现 ) ,8个消费者(至少是0个消费者在访问缓冲区域,最多5个消费者线程访问缓冲区)

我的那个代码无法做到 这点

2. raii用法错误。







如果去掉,按照我的做法,虽然有3个子线程运行,但是违背了原意: 2个同时在运行的生产者。


[Quote=引用 6 楼 的回复:]
InitData虽没调用到,但要提一下iterator的用法

C/C++ code

deque<int>::iterator iter =dq.begin();

for(; iter!= dq.end(); iter++) //这样就可以了,不要搞太复杂
{
*iter=0;
}


while(1)用错了
正确的应是……
[/Quote]
stjay 2012-07-10
  • 打赏
  • 举报
回复
InitData虽没调用到,但要提一下iterator的用法
    deque<int>::iterator iter =dq.begin();

for(; iter!= dq.end(); iter++) //这样就可以了,不要搞太复杂
{
*iter=0;
}


while(1)用错了
正确的应是
while(dq.empty()); //空,等到有数据
while(dq.size() == BUFFER_MAX_SIZE); //满了,等到有空位

不过不建议这么做
while(表达式); 这个无法预测结束时机,可能一直死循环,会消耗大量CPU资源
可以加Sleep(0),但还是不够理想


raii用法错
CritHelper ch;
CritHelpIO chi;
都是局部对象,注意其生存期(只在函数内或函数某代码块内),不能起到全局临界的作用(这里的函数都是全局 )
而且有大错误就是在构造里InitializeCriticalSection、在析构里DeleteCriticalSection

正确用法是
建一个CCriticalSection类,构造里InitializeCriticalSection,析构里DeleteCriticalSection,并且要保证CRITICAL_SECTION cs的生存期有效(如要放在全局区里)
CritHelper只负责EnterCriticalSection和LeaveCriticalSection
zhanshen2891 2012-07-10
  • 打赏
  • 举报
回复
while(1){}你在这死循环是干什么?
liuzu2016 2012-07-10
  • 打赏
  • 举报
回复
用信号量解决的问题,
1个生产者 1个消费者。




g_hFullSemaphore = CreateSemaphore(NULL,1,1,NULL);



g_hEmptySemaphore = CreateSemaphore(NULL,0,1,NULL);

//生产者
DWORD WINAPI Producer(LPVOID lpPara)
{
while(g_continue){
WaitForSingleObject(g_hFullSemaphore,INFINITE);

WaitForSingleObject(g_hMutex,INFINITE);
Produce();
Append();
Sleep(1500);

ReleaseMutex(g_hMutex);


ReleaseSemaphore(g_hEmptySemaphore,1,NULL); //唤醒消费者


}
return 0;
}

//消费者
DWORD WINAPI Consumer(LPVOID lpPara)
{
while(g_continue){
WaitForSingleObject(g_hEmptySemaphore,INFINITE);
WaitForSingleObject(g_hMutex,INFINITE);
Take();
Consume();
Sleep(1500);
ReleaseMutex(g_hMutex);
ReleaseSemaphore(g_hFullSemaphore,1,NULL); //唤醒生产者
}
return 0;
}





[Quote=引用 8 楼 的回复:]
另外:把题目改成 1个生产者,1个消费者的模型

代码也是有问题的,


//队列中添加数据
void put(int n)
{
CritHelper ch;

if(dq.size()==BUFFER_MAX_SIZE) //满了
{
while(1){}; //等到有空位

}


不知道何时有有空位, Sleep的话,但是时间不好设置。
……
[/Quote]
liuzu2016 2012-07-10
  • 打赏
  • 举报
回复
另外:把题目改成 1个生产者,1个消费者的模型

代码也是有问题的,


//队列中添加数据
void put(int n)
{
CritHelper ch;

if(dq.size()==BUFFER_MAX_SIZE) //满了
{
while(1){}; //等到有空位

}


不知道何时有有空位, Sleep的话,但是时间不好设置。






[Quote=引用 7 楼 的回复:]
今早看了会资料,发现错误很多

1 一般是用 信号量,之所以用信号量,原因:可以使多个线程同时访问 同一资源

比如 8个生产者线程(缓冲区大小为5,,循环队列作为缓冲区,可以用数组实现 ) ,8个消费者(至少是0个消费者在访问缓冲区域,最多5个消费者线程访问缓冲区)

我的那个代码无法做到 这点

2. raii用法错误。







如果去掉,按照我的做法,虽……
[/Quote]
liuzu2016 2012-07-09
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

InitData()里漏了 iter++
CritHelper ch; 不知是不是伪代码?局部的临界?这样用不行的吧
while(1){};不合理,会耗尽CPU,单线程下用,直接挂掉
[/Quote]

1.InitData这个函数 基本报废了

看 2楼

2. 我实现了代码,你看对不对

3,while(1);为什么不合理,难道 ::Sleep(几秒钟) ????

liuzu2016 2012-07-09
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
InitData()里漏了 iter++
CritHelper ch; 不知是不是伪代码?局部的临界?这样用不行的吧
while(1){};不合理,会耗尽CPU,单线程下用,直接挂掉
[/Quote]

while(1)是表示等待的意思啊


上完整代码:


#include "stdafx.h"
#include <process.h>
#include <windows.h>
#include<deque>
using std::deque;

#include<iostream>
using std::cout;
using std::endl;



int const BUFFER_MAX_SIZE =10; //BUFFER_MAX_SIZE个大小的缓冲区

deque<int>dq;



class CritHelper
{
//临界区帮助类 raii
CRITICAL_SECTION cs;
public:
CritHelper()
{
::InitializeCriticalSection(&cs);
::EnterCriticalSection(&cs);
}

~CritHelper()
{
::LeaveCriticalSection(&cs);
::DeleteCriticalSection(&cs);
}

};




class CritHelpIO
{
//临界区帮助类 raii
CRITICAL_SECTION cs;

public:
CritHelpIO()
{
::InitializeCriticalSection(&cs);
::EnterCriticalSection(&cs);
}

~CritHelpIO()
{
::LeaveCriticalSection(&cs);
::DeleteCriticalSection(&cs);
}

};






//初始化数据,子线程以外先调用
void InitData()
{
deque<int>::iterator iter =dq.begin();

for(int i=1;(i<=BUFFER_MAX_SIZE )&& (iter!= dq.end()); i++)
{
*iter=0;
}

}


//队列中添加数据
void put(int n)
{
CritHelper ch;

if(dq.size()==BUFFER_MAX_SIZE) //满了
{
while(1){}; //等到有空位

}

{
CritHelpIO chi;

cout<<"进入的数据位:"<<n<<endl;

}

dq.push_back(n);

}




//获取数据
void get()
{

int val;

CritHelper ch;

if(dq.empty()) //空
{
while(1){}; //等到有数据

}

val=dq.front();

{
CritHelpIO chi;

cout<<"取出的数据位:"<<val<<endl;

}

dq.pop_front();

}


unsigned int _stdcall Produce(VOID* n)
{
int*p =(int*)n;

for( int i=0 ;i<*p ; i++)
{
put(i);
}
return 0;
}




unsigned int _stdcall Consumer(VOID* n)
{
int *p=(int*)n;
for( int i=0 ;i<*p ; i++)
{
get();

}
return 0;

}





int main()
{

int val=10;
HANDLE hWnd1=(HANDLE)_beginthreadex(NULL,0,Produce,&val,0,NULL);
HANDLE hWnd2=(HANDLE)_beginthreadex(NULL,0,Produce,&val,0,NULL);



int val2=20;
HANDLE hWnd3=(HANDLE)_beginthreadex(NULL,0,Consumer,&val2,0,NULL);



Sleep(50000);

return 0;

}


stjay 2012-07-09
  • 打赏
  • 举报
回复
InitData()里漏了 iter++
CritHelper ch; 不知是不是伪代码?局部的临界?这样用不行的吧
while(1){};不合理,会耗尽CPU,单线程下用,直接挂掉

16,465

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧