问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

windows 多线程问题 用windows api提供的函数创建4个线程 并用WaitForMultipleObjects 但结果有问题

发布网友 发布时间:2022-05-03 01:17

我来回答

2个回答

热心网友 时间:2023-10-10 08:41

#include<windows.h>
#include<fstream.h>
#include<stdio.h>
#include<string>
#include<conio.h>

//定义一些常量;
//本程序允许的最大临界区数;
#define MAX_BUFFER_NUM 10
//秒到微秒的乘法因子;
#define INTE_PER_SEC 1000
//本程序允许的生产和消费线程的总数;
#define MAX_THREAD_NUM 64

//定义一个结构,记录在测试文件中指定的每一个线程的参数
struct ThreadInfo
{
int serial; //线程序列号
char entity; //是P还是C
double delay; //线程延迟
int thread_request[MAX_THREAD_NUM]; //线程请求队列
int n_request; //请求个数
};

//全局变量的定义

//临界区对象的声明,用于管理缓冲区的互斥访问;
CRITICAL_SECTION PC_Critical[MAX_BUFFER_NUM];
int Buffer_Critical[MAX_BUFFER_NUM]; //缓冲区声明,用于存放产品;
HANDLE h_Thread[MAX_THREAD_NUM]; //用于存储每个线程句柄的数组;
ThreadInfo Thread_Info[MAX_THREAD_NUM]; //线程信息数组;
HANDLE empty_semaphore; //一个信号量;
HANDLE h_mutex; //一个互斥量;
DWORD n_Thread = 0; //实际的线程的数目;
DWORD n_Buffer_or_Critical; //实际的缓冲区或者临界区的数目;
HANDLE h_Semaphore[MAX_THREAD_NUM]; //生产者允许消费者开始消费的信号量;

//生产消费及辅助函数的声明
void Proce(void *p);
void Consume(void *p);
bool IfInOtherRequest(int);
int FindProcePositon();
int FindBufferPosition(int);

int main(void)
{
//声明所需变量;
DWORD wait_for_all;
ifstream inFile;

//初始化缓冲区;
for(int i=0;i< MAX_BUFFER_NUM;i++)
Buffer_Critical[i] = -1;
//初始化每个线程的请求队列;
for(int j=0;j<MAX_THREAD_NUM;j++){
for(int k=0;k<MAX_THREAD_NUM;k++)
Thread_Info[j].thread_request[k] = -1;
Thread_Info[j].n_request = 0;
}
//初始化临界区;
for(i =0;i< MAX_BUFFER_NUM;i++)
InitializeCriticalSection(&PC_Critical[i]);

//打开输入文件,按照规定的格式提取线程等信息;
inFile.open("test.txt");
//从文件中获得实际的缓冲区的数目;
inFile >> n_Buffer_or_Critical;
inFile.get();
printf("输入文件是:\n");
//回显获得的缓冲区的数目信息;
printf("%d \n",(int) n_Buffer_or_Critical);
//提取每个线程的信息到相应数据结构中;
while(inFile){
inFile >> Thread_Info[n_Thread].serial;
inFile >> Thread_Info[n_Thread].entity;
inFile >> Thread_Info[n_Thread].delay;
char c;
inFile.get(c);
while(c!='\n'&& !inFile.eof()){
inFile>> Thread_Info[n_Thread].thread_request[Thread_Info[n_Thread].n_request++];
inFile.get(c);
}
n_Thread++;
}

//回显获得的线程信息,便于确认正确性;
for(j=0;j<(int) n_Thread;j++){
int Temp_serial = Thread_Info[j].serial;
char Temp_entity = Thread_Info[j].entity;
double Temp_delay = Thread_Info[j].delay;
printf(" \n thread%2d %c %f ",Temp_serial,Temp_entity,Temp_delay);
int Temp_request = Thread_Info[j].n_request;
for(int k=0;k<Temp_request;k++)
printf(" %d ", Thread_Info[j].thread_request[k]);
cout<<endl;
}
printf("\n\n");

//创建在模拟过程中几个必要的信号量
empty_semaphore=CreateSemaphore(NULL,n_Buffer_or_Critical,n_Buffer_or_Critical,
"semaphore_for_empty");
h_mutex = CreateMutex(NULL,FALSE,"mutex_for_update");

//下面这个循环用线程的ID号来为相应生产线程的产品读写时所
//使用的同步信号量命名;
for(j=0;j<(int)n_Thread;j++){
std::string lp ="semaphore_for_proce_";
int temp =j;
while(temp){
char c = (char)(temp%10);
lp+=c;
temp/=10;
}
h_Semaphore[j+1]=CreateSemaphore(NULL,0,n_Thread,lp.c_str());
}

//创建生产者和消费者线程;
for(i =0;i< (int) n_Thread;i++){
if(Thread_Info[i].entity =='P')
h_Thread[i]= CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Proce),
&(Thread_Info[i]),0,NULL);
else
h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Consume),
&(Thread_Info[i]),0,NULL);
}

//主程序等待各个线程的动作结束;
wait_for_all = WaitForMultipleObjects(n_Thread,h_Thread,TRUE,-1);
printf(" \n \nALL Procer and consumer have finished their work. \n");
printf("Press any key to quit!\n");
_getch();
return 0;
}

//确认是否还有对同一产品的消费请求未执行;
bool IfInOtherRequest(int req)
{
for(int i=0;i<n_Thread;i++)
for(int j=0;j<Thread_Info[i].n_request;j++)
if(Thread_Info[i].thread_request[j] == req)
return TRUE;

return FALSE;
}

//找出当前可以进行产品生产的空缓冲区位置;
int FindProcePosition()
{
int EmptyPosition;
for (int i =0;i<n_Buffer_or_Critical;i++)
if(Buffer_Critical[i] == -1){
EmptyPosition = i;
//用下面这个特殊值表示本缓冲区正处于被写状态;
Buffer_Critical[i] = -2;
break;
}
return EmptyPosition;
}

//找出当前所需生产者生产的产品的位置;
int FindBufferPosition(int ProPos)
{
int TempPos;
for (int i =0 ;i<n_Buffer_or_Critical;i++)
if(Buffer_Critical[i]==ProPos){
TempPos = i;
break;
}
return TempPos;
}

//生产者进程
void Proce(void *p)
{
//局部变量声明;
DWORD wait_for_semaphore,wait_for_mutex,m_delay;
int m_serial;

//获得本线程的信息;
m_serial = ((ThreadInfo*)(p))->serial;
m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC);

Sleep(m_delay);
//开始请求生产
printf("Procer %2d sends the proce require.\n",m_serial);

//确认有空缓冲区可供生产,同时将空位置数empty减1;用于生产者和消费者的同步;
wait_for_semaphore = WaitForSingleObject(empty_semaphore,-1);

//互斥访问下一个可用于生产的空临界区,实现写写互斥;
wait_for_mutex = WaitForSingleObject(h_mutex,-1);
int ProcePos = FindProcePosition();
ReleaseMutex(h_mutex);

//生产者在获得自己的空位置并做上标记后,以下的写操作在生产者之间可以并发;
//核心生产步骤中,程序将生产者的ID作为产品编号放入,方便消费者识别;
printf("Procer %2d begin to proce at position %2d.\n",m_serial,ProcePos);
Buffer_Critical[ProcePos] = m_serial;
printf("Procer %2d finish procing :\n ",m_serial);
printf(" position[ %2d ]:%3d \n" ,ProcePos,Buffer_Critical[ProcePos]);
//使生产者写的缓冲区可以被多个消费者使用,实现读写同步;
ReleaseSemaphore(h_Semaphore[m_serial],n_Thread,NULL);
}

//消费者进程
void Consume(void * p)
{
//局部变量声明;
DWORD wait_for_semaphore,m_delay;
int m_serial,m_requestNum; //消费者的序列号和请求的数目;
int m_thread_request[MAX_THREAD_NUM];//本消费线程的请求队列;

//提取本线程的信息到本地;
m_serial = ((ThreadInfo*)(p))->serial;
m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC);
m_requestNum = ((ThreadInfo *)(p))->n_request;
for (int i = 0;i<m_requestNum;i++)
m_thread_request[i] = ((ThreadInfo*)(p))->thread_request[i];

Sleep(m_delay);
//循环进行所需产品的消费
for(i =0;i<m_requestNum;i++){

//请求消费下一个产品
printf("Consumer %2d request to consume %2d proct\n",m_serial,m_thread_request[i]);
//如果对应生产者没有生产,则等待;如果生产了,允许的消费者数目-1;实现了读写同步;
wait_for_semaphore=WaitForSingleObject(h_Semaphore[m_thread_request[i]],-1);

//查询所需产品放到缓冲区的号
int BufferPos=FindBufferPosition(m_thread_request[i]);

//开始进行具体缓冲区的消费处理,读和读在该缓冲区上仍然是互斥的;
//进入临界区后执行消费动作;并在完成此次请求后,通知另外的消费者本处请求已
//经满足;同时如果对应的产品使用完毕,就做相应处理;并给出相应动作的界面提
//示;该相应处理指将相应缓冲区清空,并增加代表空缓冲区的信号量;
EnterCriticalSection(&PC_Critical[BufferPos]);

printf("Consumer%2d begin to consume %2d proct \n",m_serial,m_thread_request[i]);
((ThreadInfo*)(p))->thread_request[i] =-1;

if(!IfInOtherRequest(m_thread_request[i])){
Buffer_Critical[BufferPos] = -1;//标记缓冲区为空;
printf("Consumer%2d finish consuming %2d:\n ",m_serial,m_thread_request[i]);
printf(" position[ %2d ]:%3d \n" ,BufferPos,Buffer_Critical[BufferPos]);
ReleaseSemaphore(empty_semaphore,1,NULL);
}
else{
printf("Consumer %2d finish consuming proct %2d\n ",m_serial,m_thread_request[i]);
}
//离开临界区
LeaveCriticalSection(&PC_Critical[BufferPos]);

}
}

看函数就行

热心网友 时间:2023-10-10 08:41

控制台是个共享资源,要进行互斥访问,修改如下:
#include <windows.h>
#include <process.h>
#include <iostream>
HANDLE mute=::CreateMutex(0,0,0);
DWORD WINAPI thread_a(LPVOID hParameter)
{::WaitForSingleObject(mute,-1);
printf("this is thread 1\n");
::ReleaseMutex(mute);
return 0;
}
DWORD WINAPI thread_b(LPVOID hParameter)
{
::WaitForSingleObject(mute,-1);
printf("this is thread 2\n");
::ReleaseMutex(mute);
return 0;
}
DWORD WINAPI thread_c(LPVOID hParameter)
{::WaitForSingleObject(mute,-1);
printf("this is thread 3\n");
::ReleaseMutex(mute);
return 0;
}
DWORD WINAPI thread_d(LPVOID hParameter)
{::WaitForSingleObject(mute,-1);
printf("this is thread 4\n");
::ReleaseMutex(mute);
return 0;
}

int main(int avg,char* arg)
{
HANDLE h[4];
DWORD dw;
h[0] = ::CreateThread(NULL,NULL,thread_a,NULL,0,&dw);
h[1] = ::CreateThread(NULL,NULL,thread_b,NULL,0,&dw);
h[2] = ::CreateThread(NULL,NULL,thread_c,NULL,0,&dw);
h[3] = ::CreateThread(NULL,NULL,thread_d,NULL,0,&dw);
::WaitForMultipleObjects(4,h,TRUE,INFINITE);
return 0;
}
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
2024年9月30日遇见贵人好吗2024年9月30日是遇见贵人的黄道吉日吗 什么算助攻 肛肠疾病防治 直肠癌吃什么好? 大同肛肠癌早期怎么办 2011年放过什么电影?全一点哦 带“飞鸟”的诗句大全(190句) “飞鸟”开头的诗句 含飞鸟·的诗句 带“飞鸟”的五言诗句 我们想研究的问题: 1为什么变速器上有那么多个齿轮? 中国应如何应对美国商务部启动反倾销、反补贴调查? 关于自行车研究课题的结题报告,很急,要短,给所有分 Java 线程中调用wait为什么一定要在同步代码块中? 关于自行车研究课题的结题报告,很急 c语言中API函数的使用 自行车研究报告 我想研究的问题: 我们想研究的问题: C++里怎么调用wait 关于自行车的研究报告(500字左右) 急急急急急急急急急急急急急急急急! 新强联哪个领域最值得买?新强联2021年度报告全文?新强联今天有机构调研吗? 线程wait() notify if while 涂料胶粘剂产品经理是干嘛的 曾经风靡全国的痞子派鼻祖作家王朔,为何作品现在无人问津? 临沂目前痞子数量是多少? 痞子的作品有哪些? 谁知道“流氓”一词的来历啊? 为什么要有“流氓”一词?它的来源是哪? 为什么台湾偶像剧“和”字要读成han第四声 诺基亚系列不带GPS导航的手机。 报价 哪一个更好一些?功能上有什么区别? 不带GPS的手机可以装电子地图吗?比如呢? API函数GetMenuItemCount的用法 中国连续多少年成全球遭遇反倾销调查最多国家? API函数怎么执行实现的? 土耳其多少人口 土耳其人 土耳其人科森(Sultan Kosen)有多高 土耳其到底是欧洲人还是阿拉伯人,怎么军队中好多长的象西欧人的金发 棕发 长脸? 请问土耳其人的平均身高 没有进行学生票优惠资质核验,先在网上买了学生票,可以到站再核验吗?可以刷身份证进站? 世界最高的人是谁 土耳其有多少人 程序员(软考)都考些什么、c语言、数据结构、软件工程、java还有其他的什么没有。。。具体点的。非常感谢 嘴唇有一块变白了是什么意思。 学生票第二次买票需要核验吗 嘴唇一半红润一半发白怎么回事 嘴唇一块发白,会不会是白癜风,按压白的更厉害,已经有好几个月了! 嘴唇缺了一点点颜色怎么办 腊鸡腌咸了可以放醋泡吗 我买的腊鸡咸死了,怎么做好吃 嘴唇出现苍白色,是身体哪里出了问题?