实验2线程同步机制
实验2 线程同步机制
一、实验目的:
通过观察共享数据资源但不受控制的两个线程的并发运行输出结果,体会同步机制的必要性和重要性。然后利用现有操作系统提供的同步机制编程实现关于该两个线程的有序控制,同时要求根据同步机制的Peterson软件解决方案尝试自己编程实现同步机制和用于同一问题的解决,并基于程序运行时间长短比较两种同步机制。
二、实验设计
I基于给定银行账户间转账操作模拟代码作为线程执行代码,在主线程中创建两个并发线程,编程实现并观察程序运行结果和予以解释说明。
II利用Windows互斥信号量操作函数解决上述线程并发问题,并分析、尝试和讨论线程执行体中有关信号量操作函数调用的正确位置。
III根据同步机制的Peterson软件解决方案尝试自己编程实现线程同步机制和用于上述线程并发问题的解决,并基于程序运行时间长
短将其与基于Windows互斥信号量的线程同步机制的效率展开比较。其间,可规定线程主体代码循环执行1000000次
三、源程序清单和说明
1未利用互斥信号量
#include <>
#include <>
#include <>
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 <>
#include <>
#include <>
#define COUNT 1000000
int 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 <>
#include <>
#include <>
#define COUNT 1000000
int 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;
repeat
while flag j do no_op;
flag i := true;
临界区
flag i := false;
until false;
4.进程互斥算法3设置访问标志
Var flag i, flag j: boolean :=false, false;
repeat