多线程练习题

来源:互联网 发布:navicat 编写sql语句 编辑:程序博客网 时间:2024/05/17 00:00

题目描述:

子线程循环 10次,接着主线程循环 100次,接着又回到子线程循环 10次,接着再回到主线程又循环 100次,如此循环50次,试写出代码。

题目解析:首先不计较整体循环50次,只是需要进行一次整体循环,设计两个信号量,一个信号量hThreadSemp,用于计数子线程的输出过程,一个信号量hMainSemp用于计数主线程的输出过程,

首先子线程输出10次,也即在第十次输出完成之后需要,触发信号量hMainSemp,进行主线程信号量增加100,使得主线程进行输出,而后,主线程输出第一百次完成之后触发信号量hThreadSemp,子线程信号量增加10,进行子线程的输出,同上输出10次之后进行主线程信号量的触发,使得主线程输出100次,这样,整体循环就完成了。

#include<iostream>#include<Windows.h>using namespace std;HANDLE hThreadSemp;HANDLE hMainSemp;CRITICAL_SECTION g_cs;int LOOPCOUNT=0;DWORD Thread(LPVOID){DWORD nCount=0;while(1){::WaitForSingleObject(hThreadSemp,INFINITE);::EnterCriticalSection(&g_cs);cout<<"这是子循环第"<<nCount<<"次"<<endl;nCount++;if(nCount==10){LONG ht;::ReleaseSemaphore(hMainSemp,100,&ht);nCount=0;}::LeaveCriticalSection(&g_cs);if(LOOPCOUNT==50){break;}}return 0;}int main(){hThreadSemp=::CreateSemaphoreA(NULL,10,10,NULL);hMainSemp=::CreateSemaphoreA(NULL,0,100,NULL);::InitializeCriticalSection(&g_cs);int nCount=100;LONG thread;HANDLE hThread=NULL;DWORD tmp;if(hThreadSemp!=INVALID_HANDLE_VALUE){hThread=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Thread,NULL,0,&tmp);}int index=0;while(LOOPCOUNT!=50){//等待子循环执行完10次index++;while(1){::WaitForSingleObject(hMainSemp,INFINITE);::EnterCriticalSection(&g_cs);cout<<"这是主循环第"<<100-nCount<<"次"<<endl;if(100-nCount==99){//继续执行子循环::ReleaseSemaphore(hThreadSemp,10,&thread);::LeaveCriticalSection(&g_cs);break;}nCount--;::LeaveCriticalSection(&g_cs);}//继续执行主循环nCount=100;while(1){::WaitForSingleObject(hMainSemp,INFINITE);::EnterCriticalSection(&g_cs);cout<<"这是主循环第"<<100-nCount<<"次"<<endl;if(100-nCount==99){::ReleaseSemaphore(hThreadSemp,10,&thread);::LeaveCriticalSection(&g_cs);break;}::LeaveCriticalSection(&g_cs);nCount--;}LOOPCOUNT++;nCount=100;}::WaitForSingleObject(hThread,INFINITE);//等待子线程返回::DeleteCriticalSection(&g_cs);CloseHandle(hThreadSemp);CloseHandle(hMainSemp);CloseHandle(hThread);}

这样就能完成我们的需要了。循环50次,每一次主循环中进行四次小的循环

练习题2:编写一个程序,开启3个线程,这3个线程的ID分别为ABC,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC.依次递推。

解题思路:我们可以设定三个信号量,信号量A,开始是触发状态,输出A之后,触发信号量B,输出B,随即触发信号量C,输出C,循环十次即可,代码如下:

// 321.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"int _tmain(int argc, _TCHAR* argv[]){return 0;}#include<iostream>#include<Windows.h>using namespace std;int nCount=0;HANDLE hSempA;HANDLE hSempB;HANDLE hSempC;DWORD ThreadA(){while(nCount!=10){::WaitForSingleObject(hSempA,INFINITE);cout<<"A";::ReleaseSemaphore(hSempB,1,NULL);}return 0;}DWORD ThreadB(){while(nCount!=10){::WaitForSingleObject(hSempB,INFINITE);cout<<"B";::ReleaseSemaphore(hSempC,1,NULL);}return 0;}DWORD ThreadC(){while(1){::WaitForSingleObject(hSempC,INFINITE);cout<<"C"<<nCount;cout<<endl;nCount++;if(nCount==10){::ReleaseSemaphore(hSempA,1,NULL);break;}::ReleaseSemaphore(hSempA,1,NULL);}return 0;}int main(){//首先初始化信号量 ABC hSempA=::CreateSemaphoreA(NULL,1,1,NULL);hSempB=::CreateSemaphoreA(NULL,0,1,NULL);hSempC=::CreateSemaphoreA(NULL,0,1,NULL);HANDLE hThreadA,hThreadB,hThreadC;//开辟线程DWORD tmp;hThreadA=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadA,NULL,0,&tmp);hThreadB=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadB,NULL,0,&tmp);hThreadC=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadC,NULL,0,&tmp);::WaitForSingleObject(hThreadA,INFINITE);::WaitForSingleObject(hThreadC,INFINITE);::WaitForSingleObject(hThreadC,INFINITE);CloseHandle(hThreadA);CloseHandle(hThreadB);CloseHandle(hThreadC);CloseHandle(hSempA);CloseHandle(hSempB);CloseHandle(hSempC);}
结果如下:

我们可以看到多输出了AB,分析当线程A,第十次输出A,时,nCount的值是9,,然后等待信号量A,被触发,当线程C第十次输出C的时候,触发信号量A,那么线程A就会继续执行,输出多输出了,问题在于等待信号量的过程中nCount可能发生变化,产生了错误,所以信号量触发之后也要检测nCount的值,这样就能完美控制了

// 321.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"int _tmain(int argc, _TCHAR* argv[]){return 0;}#include<iostream>#include<Windows.h>using namespace std;int nCount=0;HANDLE hSempA;HANDLE hSempB;HANDLE hSempC;DWORD ThreadA(){while(nCount!=10){::WaitForSingleObject(hSempA,INFINITE);if(nCount!=10)cout<<"A";::ReleaseSemaphore(hSempB,1,NULL);}return 0;}DWORD ThreadB(){while(nCount!=10){::WaitForSingleObject(hSempB,INFINITE);if(nCount!=10)cout<<"B";::ReleaseSemaphore(hSempC,1,NULL);}return 0;}DWORD ThreadC(){while(1){::WaitForSingleObject(hSempC,INFINITE);cout<<"C"<<nCount;cout<<endl;nCount++;if(nCount==10){::ReleaseSemaphore(hSempA,1,NULL);break;}::ReleaseSemaphore(hSempA,1,NULL);}return 0;}int main(){//首先初始化信号量 ABC hSempA=::CreateSemaphoreA(NULL,1,1,NULL);hSempB=::CreateSemaphoreA(NULL,0,1,NULL);hSempC=::CreateSemaphoreA(NULL,0,1,NULL);HANDLE hThreadA,hThreadB,hThreadC;//开辟线程DWORD tmp;hThreadA=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadA,NULL,0,&tmp);hThreadB=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadB,NULL,0,&tmp);hThreadC=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadC,NULL,0,&tmp);::WaitForSingleObject(hThreadA,INFINITE);::WaitForSingleObject(hThreadC,INFINITE);::WaitForSingleObject(hThreadC,INFINITE);CloseHandle(hThreadA);CloseHandle(hThreadB);CloseHandle(hThreadC);CloseHandle(hSempA);CloseHandle(hSempB);CloseHandle(hSempC);}

练习题三:

有四个线程1、234。线程1的功能就是输出1,线程2的功能就是输出2,以此类推.........现在有四个文件ABCD。初始都为空。现要让四个文件呈如下格式:

A1 2 3 4 1 2....

B2 3 4 1 2 3....

C3 4 1 2 3 4....

D4 1 2 3 4 1....

解题思路:设置4个信号量,

第一次进行输出的饿时候  

SemA ----A1

SemB ----A2  B2

SemC ----A3  B3   C3

SemD ----A4  B4   C4   D4

第2...3..4次输出的时候就是

SemA ----A1   B1   C1   D1

SemB ----A2  B2    C2   D2

SemC ----A3  B3   C3   D3

SemD ----A4  B4   C4   D4

区别第一次输出的时候,就可以完美实现结果了,等待实现源代码

// 321.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"int _tmain(int argc, _TCHAR* argv[]){return 0;}#include<iostream>#include<Windows.h>#include<fstream>using namespace std;HANDLE hSempA,hSempB,hSempC,hSempD;bool isFirst=true;HANDLE hThread[4]={0};void WriteFile(char m){ofstream out("A.txt",ios::app);out.write(&m,1);out.close();cout<<"A.txt  "<<m<<"\n";out.open("B.txt",ios::app);out.write(&m,1);out.close();cout<<"B.txt  "<<m<<"\n";out.open("C.txt",ios::app);out.write(&m,1);out.close();cout<<"C.txt  "<<m<<"\n";out.open("D.txt",ios::app);out.write(&m,1);out.close();cout<<"D.txt  "<<m<<"\n";}DWORD ThreadA(){while(true){if(isFirst){::WaitForSingleObject(hSempA,INFINITE);if(isFirst){ofstream out("A.txt",ios::app);out.write("1",strlen("1"));out.close();cout<<"A.txt  "<<"1\n";::ReleaseSemaphore(hSempB,1,NULL);}else{WriteFile('1');::ReleaseSemaphore(hSempB,1,NULL);}}else{::WaitForSingleObject(hSempA,INFINITE);WriteFile('1');::ReleaseSemaphore(hSempB,1,NULL);}}return 0;}DWORD ThreadB(){while(1){if(isFirst){::WaitForSingleObject(hSempB,INFINITE);if(isFirst){ofstream out("A.txt",ios::app);out.write("2",strlen("2"));out.close();cout<<"A.txt  "<<"2\n";out.open("B.txt",ios::app);out.write("2",strlen("2"));out.close();cout<<"B.txt  "<<"2\n";::ReleaseSemaphore(hSempC,1,NULL);}else{WriteFile('2');::ReleaseSemaphore(hSempC,1,NULL);}}else{::WaitForSingleObject(hSempB,INFINITE);WriteFile('2');::ReleaseSemaphore(hSempC,1,NULL);}}return 0;}DWORD ThreadC(){while(1){if(isFirst){::WaitForSingleObject(hSempC,INFINITE);if(isFirst){ofstream out("A.txt",ios::app);out.write("3",strlen("3"));out.close();cout<<"A.txt  "<<"3\n";out.open("B.txt",ios::app);out.write("3",strlen("3"));out.close();cout<<"B.txt  "<<"3\n";out.open("C.txt",ios::app);out.write("3",strlen("3"));out.close();cout<<"C.txt  "<<"3\n";::ReleaseSemaphore(hSempD,1,NULL);}else{WriteFile('3');::ReleaseSemaphore(hSempD,1,NULL);}}else{::WaitForSingleObject(hSempC,INFINITE);WriteFile('3');::ReleaseSemaphore(hSempD,1,NULL);}}return 0;}DWORD ThreadD(){while(1){if(isFirst){::WaitForSingleObject(hSempD,INFINITE);ofstream out("A.txt",ios::app);out.write("4",strlen("4"));out.close();cout<<"A.txt  "<<"4\n";out.open("B.txt",ios::app);out.write("4",strlen("4"));out.close();cout<<"B.txt  "<<"4\n";out.open("C.txt",ios::app);out.write("4",strlen("4"));out.close();cout<<"C.txt  "<<"4\n";out.open("D.txt",ios::app);out.write("4",strlen("4"));out.close();cout<<"D.txt  "<<"4\n";isFirst=false;::ReleaseSemaphore(hSempA,1,NULL);}else{::WaitForSingleObject(hSempD,INFINITE);WriteFile('4');::ReleaseSemaphore(hSempA,1,NULL);}}return 0;}int main(){::DeleteFileA("A.txt");::DeleteFileA("B.txt");::DeleteFileA("C.txt");::DeleteFileA("D.txt");hSempA=::CreateSemaphoreA(NULL,1,1,NULL);hSempB=::CreateSemaphoreA(NULL,0,1,NULL);hSempC=::CreateSemaphoreA(NULL,0,1,NULL);           hSempD=::CreateSemaphoreA(NULL,0,1,NULL);DWORD tmp=0;hThread[0]=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadA,NULL,0,&tmp);hThread[1]=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadB,NULL,0,&tmp);hThread[2]=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadC,NULL,0,&tmp);hThread[3]=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadD,NULL,0,&tmp);::WaitForMultipleObjects(4,hThread,true,INFINITE);return 0;}

这里有一个之前重复出现的问题就是在进行标志位判断的时候(本题中是isFirst)首先进行判断,而后是等待信号量触发,(这里面就容易出问题了),在等待信号量触发的过程中就出现了,如果有其他的线程已经将isFirst触发了,而我们已经检测过了,isFirst是未触发状态,所以我们就需要进行再次判断,如果没有已经触发,则进行触发操作,否则进行未触发操作

0 0