线程面试题之五:放水果问题
2014-08-14 16:15
1216 查看
桌上有一空盘,允许存放一只水果。爸爸可向盘中放苹果,也可向盘中放桔子,儿子专等吃盘中的桔子,女儿专等吃盘中的苹果。规定当盘空时一次只能放一只水果供吃者取用,请用P、V原语实现爸爸、儿子、女儿三个并发线程的同步。(南京大学计算机考研真题)
(注:在写本篇学习笔记时,本人学习和参考了网络文章,并做了借鉴,感谢各位前辈的分享。如果本文对您有所帮助,您可以随意分享,如果发现文中有误,也请指教,谢谢。本文用到的调试工具:Microsoft
Visual Studio 10,操作系统:Windows 7)
我们首先考虑同步情况即所有“等待”情况:
第一,爸爸要等待盘子为空。
第二,儿子要等待盘中水果是桔子。
第三,女儿要等待盘中水果是苹果。
接下来来考虑要互斥处理的资源,看起来盘子好像是要作互斥处理的,但由于题目中的爸爸、儿子、女儿均只有一个,并且他们访问盘子的条件都不一样,所以他们根本不会同时去访问盘子,因此盘子也就不用作互斥处理了。分析至此,这个题目已经没有难度了,下面用PV原语给出答案:
先设置三个信号量,信号量Orange表示盘中有桔子,初值为0。信号量Apple表示盘中有苹果,初值为0。信号量EmptyDish表示盘子为空,初值为1。三个人的操作流程如下所示:
1.爸爸
P(EmptyDish)
if (rand()%2==0)
{
放桔子
V(Orange)
}
else
{
放苹果
V(Apple)
}
2.儿子
P(Orange)
取桔子
V(EmptyDish)
3.女儿
P(Apple)
取苹果
V(EmptyDish)
以下为多线程实现的取水果源码:
运行结果为:
(注:在写本篇学习笔记时,本人学习和参考了网络文章,并做了借鉴,感谢各位前辈的分享。如果本文对您有所帮助,您可以随意分享,如果发现文中有误,也请指教,谢谢。本文用到的调试工具:Microsoft
Visual Studio 10,操作系统:Windows 7)
我们首先考虑同步情况即所有“等待”情况:
第一,爸爸要等待盘子为空。
第二,儿子要等待盘中水果是桔子。
第三,女儿要等待盘中水果是苹果。
接下来来考虑要互斥处理的资源,看起来盘子好像是要作互斥处理的,但由于题目中的爸爸、儿子、女儿均只有一个,并且他们访问盘子的条件都不一样,所以他们根本不会同时去访问盘子,因此盘子也就不用作互斥处理了。分析至此,这个题目已经没有难度了,下面用PV原语给出答案:
先设置三个信号量,信号量Orange表示盘中有桔子,初值为0。信号量Apple表示盘中有苹果,初值为0。信号量EmptyDish表示盘子为空,初值为1。三个人的操作流程如下所示:
1.爸爸
P(EmptyDish)
if (rand()%2==0)
{
放桔子
V(Orange)
}
else
{
放苹果
V(Apple)
}
2.儿子
P(Orange)
取桔子
V(EmptyDish)
3.女儿
P(Apple)
取苹果
V(EmptyDish)
以下为多线程实现的取水果源码:
#include "stdafx.h" #include "process.h" #include "windows.h" #include "time.h" HANDLE g_hEmptyDish; HANDLE g_hFullApple; HANDLE g_hFullOrange; HANDLE g_hEvent; const int SLEEP_TIMES = 200; // 睡眠时间(ms) const int RAND_MAX_NUM = 99999; // 随机数种子 const int FULL_TIMES = 10; // 循环总数 int g_iTimes = 1; // 循环次数 int g_iFruit = 0; BOOL g_bFlag = FALSE; // 设置控制台输出颜色 BOOL SetConsoleColor(WORD wAttributes) { HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); if (hConsole == INVALID_HANDLE_VALUE) { return FALSE; } return SetConsoleTextAttribute(hConsole, wAttributes); } unsigned int __stdcall ThreadFatherFunc(LPVOID pM) { int iRandNum = 0; srand((unsigned)time(NULL)); while (TRUE) { WaitForSingleObject(g_hEmptyDish,INFINITE); Sleep(SLEEP_TIMES); iRandNum = rand()%RAND_MAX_NUM; if (iRandNum%2 == 0) { g_iFruit++; SetConsoleColor(FOREGROUND_GREEN|FOREGROUND_INTENSITY); printf("父亲向盘中放入%d橘子\n",g_iFruit); SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); g_iTimes++; ReleaseSemaphore(g_hFullOrange,1,NULL); if (g_iTimes == FULL_TIMES) { break; } } else { g_iFruit++; SetConsoleColor(FOREGROUND_RED|FOREGROUND_INTENSITY); printf("父亲向盘中放入%d苹果\n",g_iFruit); SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); g_iTimes++; ReleaseSemaphore(g_hFullApple,1,NULL); if (g_iTimes == FULL_TIMES) { break; } } } printf("父亲发现循环次数足够,游戏结束,退出线程。\n"); return 0; } unsigned int __stdcall ThreadChildrenFunc(LPVOID pM) { int * num = (int *)pM; if (*num == 1) { SetEvent(g_hEvent); while (TRUE) { WaitForSingleObject(g_hFullOrange,INFINITE); Sleep(SLEEP_TIMES); if (g_bFlag) { break; } SetConsoleColor(FOREGROUND_GREEN); printf(" 儿子从盘中取出%d橘子\n",g_iFruit); SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); g_iFruit--; if (g_iTimes == FULL_TIMES) { // 当哥哥发现循环次数足够,则通知妹妹退出线程 g_bFlag = TRUE; ReleaseSemaphore(g_hFullApple,1,NULL); break; } ReleaseSemaphore(g_hEmptyDish,1,NULL); } printf("儿子收到消息,游戏结束,退出线程。\n"); } else { SetEvent(g_hEvent); while (TRUE) { WaitForSingleObject(g_hFullApple,INFINITE); Sleep(SLEEP_TIMES); if (g_bFlag) { break; } SetConsoleColor(FOREGROUND_RED); printf(" 女儿从盘中取出%d苹果\n",g_iFruit); SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); g_iFruit--; if (g_iTimes == FULL_TIMES) { // 当妹妹发现循环次数足够,则通知哥哥退出线程 g_bFlag = TRUE; ReleaseSemaphore(g_hFullOrange,1,NULL); break; } ReleaseSemaphore(g_hEmptyDish,1,NULL); } printf("女儿收到消息,游戏结束,退出线程。\n"); } return 0; } int _tmain(int argc, _TCHAR* argv[]) { printf("-------------------------------\n"); printf(" 取水果问题的多线程实现\n"); printf("-------------------------------\n"); int i = 0; int THD_NUM = 3; HANDLE hThread[3]; g_hEvent = CreateEvent(NULL,FALSE,FALSE,NULL); g_hEmptyDish = CreateSemaphore(NULL,1,1,NULL); g_hFullApple = CreateSemaphore(NULL,0,1,NULL); g_hFullOrange = CreateSemaphore(NULL,0,1,NULL); hThread[0] = (HANDLE)_beginthreadex(NULL,0,ThreadFatherFunc,NULL,0,NULL); for (i=1;i<THD_NUM;i++) { hThread[i] = (HANDLE)_beginthreadex(NULL,0,ThreadChildrenFunc,&i,0,NULL); WaitForSingleObject(g_hEvent,INFINITE); } WaitForMultipleObjects(THD_NUM, hThread, TRUE, INFINITE); for (i=0;i<THD_NUM;i++) { CloseHandle(hThread[i]); } CloseHandle(g_hEvent); CloseHandle(g_hEmptyDish); CloseHandle(g_hFullApple); CloseHandle(g_hFullOrange); getchar(); return 0; }
运行结果为:
相关文章推荐
- 线程安全性---面试题--i++的线程安全性问题
- 从面试题看问题之线程篇(一)
- 线程面试题之四:生产者消费者问题
- 面试题15解析-守护线程 / JAVA多线程问题及其补充
- Java面试题--多线程、并发及线程的基础问题
- 面试题_1_to_16_多线程、并发及线程的基础问题
- Java线程问题。面试题
- 飞机加油问题,据说是微软的面试题。
- RichTextBox的线程安全问题
- 深入研究Servlet线程安全性问题
- Servlet线程安全性问题
- 关于OS中第一线程的问题解决.
- 深入研究Servlet线程安全性问题
- 线程正在被中止问题的原因及解决
- 一道C语言面试题——邮票组合问题
- 请教一个有关线程的问题
- 关于线程和进程的同步问题
- 如果我是国王:关于解决 Java 编程语言线程问题的建议
- 工作线程中调用UI线程创建的窗口的UpdateData会导致Assert的问题及解决办法.
- 请教=====线程问题??????