亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

用WaitForMultipleObjects 但結果有問題,求指點啊

用WaitForMultipleObjects 但結果有問題,求指點啊

炎炎設計 2023-03-03 13:09:23
這里附上代碼和執行結果 求高手解答#include <windows.h#include <process.h>#include <iostream>DWORD WINAPI thread_a(LPVOID hParameter){printf("this is thread 1\n");return 0;}DWORD WINAPI thread_b(LPVOID hParameter){printf("this is thread 2\n");return 0;}DWORD WINAPI thread_c(LPVOID hParameter){printf("this is thread 3\n");return 0;}DWORD WINAPI thread_d(LPVOID hParameter){printf("this is thread 4\n");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;}4個線程 5個輸出,有個線程會被執行2次 求解決方案。
查看完整描述

2 回答

?
慕桂英3389331

TA貢獻2036條經驗 獲得超8個贊

#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 Produce(void *p);
void Consume(void *p); 
bool IfInOtherRequest(int);
int FindProducePositon();
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_produce_";
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)(Produce),
&(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 Producer 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 FindProducePosition()
{
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 Produce(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("Producer %2d sends the produce require.\n",m_serial);

//確認有空緩沖區可供生產,同時將空位置數empty減1;用于生產者和消費者的同步;
wait_for_semaphore = WaitForSingleObject(empty_semaphore,-1);

//互斥訪問下一個可用于生產的空臨界區,實現寫寫互斥;
wait_for_mutex = WaitForSingleObject(h_mutex,-1);
int ProducePos = FindProducePosition();
ReleaseMutex(h_mutex);

//生產者在獲得自己的空位置并做上標記后,以下的寫操作在生產者之間可以并發;
//核心生產步驟中,程序將生產者的ID作為產品編號放入,方便消費者識別;
printf("Producer %2d begin to produce at position %2d.\n",m_serial,ProducePos);
Buffer_Critical[ProducePos] = m_serial;
printf("Producer %2d finish producing :\n ",m_serial);
printf(" position[ %2d ]:%3d \n" ,ProducePos,Buffer_Critical[ProducePos]);
//使生產者寫的緩沖區可以被多個消費者使用,實現讀寫同步;
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 product\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 product \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 product %2d\n ",m_serial,m_thread_request[i]);
}
//離開臨界區
LeaveCriticalSection(&PC_Critical[BufferPos]);

}


看函數就行


查看完整回答
反對 回復 2023-03-06
?
臨摹微笑

TA貢獻1982條經驗 獲得超2個贊

控制臺是個共享資源,要進行互斥訪問,修改如下:
#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;
}


查看完整回答
反對 回復 2023-03-06
  • 2 回答
  • 0 關注
  • 106 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號