实验2 线程同步机制一、实验目的:通过观察共享数据资源但不受控制的两个线程的并发运行输出结果,体会同步机制的必要性和重要性。
然后利用现有操作系统提供的同步机制编程实现关于该两个线程的有序控制,同时要求根据同步机制的Peterson软件解决方案尝试自己编程实现同步机制和用于同一问题的解决,并基于程序运行时间长短比较两种同步机制。
二、实验设计I基于给定银行账户间转账操作模拟代码作为线程执行代码,在主线程中创建两个并发线程,编程实现并观察程序运行结果和予以解释说明。
II利用Windows互斥信号量操作函数解决上述线程并发问题,并分析、尝试和讨论线程执行体中有关信号量操作函数调用的正确位置。
III根据同步机制的Peterson软件解决方案尝试自己编程实现线程同步机制和用于上述线程并发问题的解决,并基于程序运行时间长短将其与基于Windows互斥信号量的线程同步机制的效率展开比较。
其间,可规定线程主体代码循环执行1000000次三、源程序清单和说明1未利用互斥信号量#include <windows.h>#include <stdlib.h>#include <stdio.h>int nAccount1 = 0, nAccount2 = 0;int nLoop = 0;int nTemp1, nTemp2, nRandom;DWORD WINAPI ThreadFunc(HANDLE Thread){do{nTemp1 = nAccount1;nTemp2 = nAccount2;nRandom = rand();nAccount1 = nTemp1 + nRandom;nAccount2 = nTemp2 - nRandom;nLoop++;} while ((nAccount1 + nAccount2) == 0);printf("循环次数为%d\n", nLoop);return 0;}int main(){HANDLE Thread[2];Thread[0] = CreateThread(NULL,0,ThreadFunc,NULL,0,NULL);Thread[1] = CreateThread(NULL,0,ThreadFunc,NULL,0,NULL);WaitForMultipleObjects(2,Thread,TRUE,INFINITE);CloseHandle(Thread);return 0;}2利用Windows互斥信号量#include <windows.h>#include <stdlib.h>#include <stdio.h>#define COUNT 1000000int nAccount1 = 0, nAccount2 = 0;HANDLE mutex;DWORD WINAPI ThreadFunc(HANDLE Thread){int nLoop = 0;int nTemp1, nTemp2, nRandom;WaitForSingleObject(mutex,INFINITE);do{nTemp1 = nAccount1;nTemp2 = nAccount2;nRandom = rand();nAccount1 = nTemp1 + nRandom;nAccount2 = nTemp2 - nRandom;nLoop++;ReleaseMutex(mutex);WaitForSingleObject(mutex,INFINITE);}while ((nAccount1 + nAccount2) == 0&&nLoop < COUNT);ReleaseMutex(mutex);WaitForSingleObject(mutex,INFINITE);printf("循环次数为%d\n", nLoop);ReleaseMutex(mutex);return 0;}int main(){HANDLE Thread[2];DWORD start, end;start = GetTickCount();mutex = CreateMutex(NULL,FALSE,NULL);Thread[0] = CreateThread(NULL,0,ThreadFunc,NULL,0,NULL);Thread[1] = CreateThread(NULL,0,ThreadFunc,NULL,0,NULL);WaitForMultipleObjects(2,Thread,TRUE,INFINITE);end = GetTickCount();printf("总共用时%ld\n",end-start);CloseHandle(Thread);CloseHandle(mutex);return 0;}3同步机制的Peterson#include <windows.h>#include <stdlib.h>#include <stdio.h>#define COUNT 1000000int nAccount1 = 0, nAccount2 = 0, flag[2], turn;int nLoop = 0;int nTemp1, nTemp2, nRandom;//HANDLE mutex;void request ( int id ){int other = 1 - id;flag[id] = 1;turn = other;while ( flag[other] == 1 && turn == other ){};}DWORD WINAPI ThreadFunc0(HANDLE Thread){request(0);do{nTemp1 = nAccount1;nTemp2 = nAccount2;nRandom = rand();nAccount1 = nTemp1 + nRandom;nAccount2 = nTemp2 - nRandom;nLoop++;flag[0] = 0;request(0);}while ((nAccount1 + nAccount2) == 0 && nLoop < COUNT);flag[0] = 0;request(0);flag[0] = 0;printf("循环次数为%d\n", nLoop);return 0;}DWORD WINAPI ThreadFunc1(HANDLE Thread){request(1);do{nTemp1 = nAccount1;nTemp2 = nAccount2;nRandom = rand();nAccount1 = nTemp1 + nRandom;nAccount2 = nTemp2 - nRandom;nLoop++;flag[1] = 0;request(1);}while ((nAccount1 + nAccount2) == 0 && nLoop < COUNT);flag[1] = 0;request(1);flag[1] = 0;printf("循环次数为%d\n", nLoop);return 0;}int main(){HANDLE Thread[2];DWORD start, end;start = GetTickCount();Thread[0] = CreateThread(NULL,0,ThreadFunc0,NULL,0,NULL);Thread[1] = CreateThread(NULL,0,ThreadFunc1,NULL,0,NULL);WaitForMultipleObjects(2,Thread,TRUE,INFINITE);end = GetTickCount();printf("总共用时%ld\n",end-start);CloseHandle(Thread);return 0;}四、算法及关键数据结构设计1.银行账户间转账操作模拟int nAccount1 = 0, nAccount2 = 0; //主线程创建的全局变量int nLoop = 0;int nTemp1, nTemp2, nRandom;do{nTemp1 = nAccount1;nTemp2 = nAccount2;nRandom = rand();nAccount1 = nTemp1 + nRandom;nAccount2 = nTemp2 - nRandom;nLoop++;} while ((nAccount1 + nAccount2) = = 0);printf("循环次数为%d\n", nLoop);2.进程互斥算法1−设置访问编号Var turn: integer :=i;repeat……while turn≠i do no_op;临界区turn:=j;……until false;3.进程互斥算法2−设置访问标志Var flag i, flag j: boolean :=false, false;repeatwhile flag j do no_op;flag i := true;临界区flag i := false;until false;4.进程互斥算法3−设置访问标志Var flag i, flag j: boolean :=false, false;repeatflag i := true;while flag j do no_op;临界区flag i := false;until false;5.进程互斥算法4 编号+标志Var flag i, flag j: boolean;turn: integer;repeatflag i := true; turn := j;while (flag j and turn=j) do no_op;临界区flag i := false;until false;五、实验过程中间结果屏幕截图实验结果1未利用互斥信号量2利用Windows互斥信号量3同步机制的Peterson结果分析1没有应用互斥信号量对线程进行并发控制,运行会产生错误。
2利用Windows互斥信号量后,两存取款线程可并发正确执行。
成功转账100000次。
但加大了系统的时间开销。
时间效率低。
3应用同步机制的Peterson算法后,两线程也可顺利的并发执行,成功转账100000次,但相对于Windows互斥信号量,时间明显缩短。