code link: 欢迎star
文章目录
1. 实验目的
探索、理解并掌握操作系统同步机制的设计和实现机理,针对所谓的银行账户转账同步问题,构建基于Peterson 算法的同步解决方案以及基于Windows(或Linux)操作系统同步机制(主要是互斥机制)的解决方案,并进行分析和比较。
2. 实验内容
针对所谓的银行账户转账同步问题,分析、设计和利用C 语言编程实现基于Peterson 算法的同步解决方案,以及基于Windows(或Linux)操作系统同步机制的相应解决方案,并就自编同步机制与操作系统自身同步机制的效率进行比较和分析。
3. 实验要求
同步机制及应用编程实现与比较实验功能设计要求:
- 银行账户转账同步问题的抽象及未采取同步控制情况下的编程实现;
- 基于Peterson 算法的银行账户转账同步问题解决方案;
- 基于 Windows(或 Linux)操作系统同步机制的银行账户转账同步问题解决方案;
- Peterson 算法同步机制和Windows(或Linux)操作系统同步机制的效率比较。
4. 实验思路
实验共分为三个部分。
- 第一部分,不采用同步控制机制,只在主进程申请两个银行账户的线程来实现对比。这里的核心算法参考实验指导书。
- 第二部分,采用Peterson算法进行同步。这里参考了ppt上的介绍,需要定义两个账户两个线程函数。同时添加NLoop上限值进行控制。在这部分,利用编号和标志实现线程的互斥。
- 第三部分,采用windows系统的互斥信号量进行同步线程。主要运用参考了实验指导上的函数,包括WaitForSingleObject、ReleaseMutex、CreateMutex。这里我们通过对上边两个部分的总结,将交互输出改为1000个循环一次,这样可以在一屏上输出结果,实验验证性好。
第四部分,在peterson和windows mutex代码中加入了计时部分,还修改了主线程等待机制,使计时更加准确。控制循环变量,令两者可以比较,MAXNLOOP设为10000次。
5. 程序实现
5.1. 相关环境介绍
操作系统:window 10 21H2
开发环境:Clion-2022.2.1-Windows
编译器:mwing-10.0
5.2. 实验第一部分 无同步机制
01:DWORD WINAPI ThreadExecuteZZW(LPVOID lpParameter){
02: int *pID = (int*)lpParameter;
03:
04: int nLoop = 0;
05: int nTemp1, nTemp2, nRandom;
06: do
07: {
08: cout << "thread " << *pID << " is called"<< " nLoop is " << nLoop << endl;
09: nRandom = rand();
10: nTemp1 = nAccount1;
11: nTemp2 = nAccount2;
12: nAccount1 = nTemp1 + nRandom;
13: nAccount2 = nTemp2 - nRandom;
14: ++nLoop;
15: } while ((nAccount1 + nAccount2) == 0);
16:
17: return 0;
18:}
结果符合预期,两个进程相互输出,最后两个账户结果数值之和不为0,实验结束。
5.3. 实验第二部分 Peterson算法
核心代码:
19:#define MAXLOOP 10000
20:int nAccount1 = 0;
21:int nAccount2 = 0;
22:
23:bool flag[2];
24:int turn =0;
25:int nLoop = 0;
26:DWORD WINAPI ThreadExecuteZZW0(LPVOID lpParameter){
27: int *pID = (int *)lpParameter;
28: int nTemp1, nTemp2, nRandom;
29:
30: do{
31:
32:
33: flag[0] = true;
34: turn = 1;
35: while(flag[1] && turn == 1){};
36:
37:cout << "thread "<< *pID << " is called " << "nLoop is "<< nLoop << endl;
38:
39: nRandom = rand();
40: nTemp1 = nAccount1;
41: nTemp2 = nAccount2;
42: nAccount1 = nTemp1 + nRandom;
43: nAccount2 = nTemp2 - nRandom;
44: ++nLoop;
45:
46: flag[0] = false;
47: }while((nAccount1+nAccount2)==0 && nLoop < MAXLOOP);
48:
49: return 0;
50:}
51:
52:DWORD WINAPI ThreadExecuteZZW1(LPVOID lpParameter){
53: int *pID = (int *)lpParameter;
54: int nTemp1, nTemp2, nRandom;
55: do{
56:
57:
58: flag[1] = true;
59: turn = 0;
60: while(flag[0] && turn == 0){};
61: cout << "thread "<< *pID << " is called " << "nLoop is "<< nLoop << "\n";
62: nRandom = rand();
63: nTemp1 = nAccount1;
64: nTemp2 = nAccount2;
65: nAccount1 = nTemp1 + nRandom;
66: nAccount2 = nTemp2 - nRandom;
67: ++nLoop;
68:
69: flag[1] = false;
70: }while((nAccount1+nAccount2)==0 && nLoop < MAXLOOP);
71:
72: return 0;
73:}
结果输出:
结果分析:
考虑到我们设定的NLoop上限为10000,可以看出最后程序nLoop准确地按照设定循环次数停了下了。Peterson算法实现成功。
5.4. 实验第三部分 Windows同步机制
74:#define MAXLOOP 10000
75:int nAccount1 = 0;
76:int nAccount2 = 0;
77:
78:HANDLE hMutex = CreateMutex(NULL, FALSE, "MutexToProtectCriticalResource");
79:int nLoop = 0;
80:DWORD WINAPI ThreadExecuteZZW(LPVOID lpParameter){
81: int *pID = (int *)lpParameter;
82: int nTemp1, nTemp2, nRandom;
83:
84: do{
85: WaitForSingleObject(hMutex, INFINITE);
86: if(nLoop%1000 == 0){
87: cout << "thread "<< *pID << " is called " << "nLoop is "<< nLoop << "\n";
88: }
89: nRandom = rand();
90: nTemp1 = nAccount1;
91: nTemp2 = nAccount2;
92: nAccount1 = nTemp1 + nRandom;
93: nAccount2 = nTemp2 - nRandom;
94: ++nLoop;
95: ReleaseMutex(hMutex);
96:
97: }while((nAccount1+nAccount2)==0 && nLoop < MAXLOOP);
98:
99: return 0;
100:}
通过结果来看,实验完成的非常好,进行地非常好。
5.5. 第四部分 Peterson和windows mutex同步机制效率比对
上边为peterson算法,时间为0.015s;后边的是通过api调用mutex互斥变量进行同步的结果,用时0.046s。两个实验设置循环次数为10000次。
结论是Peterson算法效率更高。
(后按:这一点的结论很容易被老师用来判断是否是自己独立完成实验 2023年10月18日10:02:25)
6. 实验汇总
6.1. 实验要求完成情况
成功完成实验要求。
6.2. 技术难点及解决方案
Peterson 算法部分。一开始输出冲突,后来发现是输出语句的位置在标志之外,没有被同步机制管控,遂修改。后边的结果非常整齐。修改前的结果类似无同步机制。
在效率对比部分之前,一直使用sleep函数进行主线程等待子线程,后来在计算时间时发现这样只会计算主线程时间,从而无法比较。后来仔细查看实验指导发现可以采用WaitForMultipleObjects函数进行主线程等待,这样直接就可以得到子线程运行的时间了。
6.3. 实验感想和经验总结
本次实验主要是对课堂上所讲述的部分同步算法的一个实践,并且以windows平台作为代码编程环境api对象实践。掌握了许多windows的api同步函数,对同步的机制有了更深的理解。
关于实验中peterson算法的效率比windows自带的mutex api效率更高的结果,是出乎我的意料的。后来思考可能mutex调用系统的函数,里面有许多安全策略需要满足,速度自然打了折扣,如果按照简单实现的话,mutex其实可以就是一个bool型变量,那么效率应该和peterson算法在本实验中的结果不相上下,甚至更快。(peterson算法有三个控制变量,而按上述实现mutex法只有一个)
6.4. 参考链接
- ZGSOS操作系统实验指导《实验课题5_同步机制及应用编程实现与比较》