📄 设计报告.txt
字号:
void acc_right(void* p)
{
DWORD m_delay;
int m_serial;
int tmp1 , tmp2, rand_num;
int counter = 0;
//get info from para
m_serial = ((ThreadInfo*) (p)) -> serial;
m_delay = (DWORD) (((ThreadInfo*)(p)) -> delay*INTE_PER_SEC);
do
{
flag[m_serial]=true;
turn=1-m_serial;
while (flag[1-m_serial] && turn==1-m_serial);
//begin critical_section
printf("I am thread %d , I am doing %05dth step\n",m_serial,counter);
tmp1 = accnt1;
tmp2 = accnt2;
rand_num = rand();
accnt1 = tmp1 - rand_num;
Sleep(m_delay);
accnt2 = tmp2 + rand_num;
accnt = accnt1 + accnt2;
//critical_section end
flag[m_serial]=false;
counter++;
printf("Now the random number is %d ; and accnt1+accnt2 = %05d\n\n",rand_num,accnt);
} while (counter<10);
printf("At last of thread %d accnt1+accnt2 = %05d\n",m_serial,accnt);
} //end acc_right
void acc_wrong(void* p)
{
DWORD m_delay;
int m_serial;
int tmp1 , tmp2, rand_num;
int counter = 0;
//get info from para
m_serial = ((ThreadInfo*) (p)) -> serial;
m_delay = (DWORD) (((ThreadInfo*)(p)) -> delay*INTE_PER_SEC);
do
{
//begin critical_section
printf("I am thread %d , I am doing %05dth step\n",m_serial,counter);
tmp1 = accnt1;
tmp2 = accnt2;
rand_num = rand();
accnt1 = tmp1 - rand_num;
Sleep(m_delay);
accnt2 = tmp2 + rand_num;
accnt = accnt1 + accnt2;
//critical_section end
counter++;
printf("Now the random number is %d ; and accnt1+accnt2 = %05d\n\n",rand_num,accnt);
} while (counter<10);
printf("At last of thread %d accnt1+accnt2 = %05d\n",m_serial,accnt);
} //end acc_wrong
任务三 同步对象解决临界区问题
一、基本信息
实践题目:同步对象解决临界区问题-兄弟问题
二、实践内容简要描述
实践目标:
学会使用Win32同步对象(临界区内核对象、信号量内核对象等);
用同步对象解决临界区问题-兄弟问题。
实践内容:
设置竞争条件:
定义两个全局变量:accnt1和accnt2,初值都为零;
创建两个线程acc1和acc2;
(1)获得一个随机数
(2)从accnt1减去这个随机数;
(3)将这个随机数加到accnt2中;
(4)正确的话,accnt1+accnt2=0。
设置条件使其不正确。
用Win32提供的同步对象实现两个线程的协作,以解决以上临界区问题,即兄弟问题。
三、实践报告主要内容
设计思路:
用一个临界区变量可以实现两个线程对临界区的访问,在每个线程进入临界区前调用EnterCriticalSection函数申请权限,离开临界区后调用LeaveCriticalSection函数释放资源从而让其他线程可以访问,这样可以阻止两个线程同时处于临界区。
主要数据结构:
struct ThreadInfo
{
int serial;
double delay;
};//存放线程的ID及其执行延时(模拟兄弟在外创业的时间)
/*volatile*/ int accnt1 = 0; //借款帐户中金额
/*volatile*/ int accnt2 = 0; //还款帐户中金额
/*volatile*/ int accnt; //借款帐户与还款帐户金额总和,应保持为0
CRITICAL_SECTION g_cs; //临界区变量,用于两个线程的互斥访问
主要代码结构:
do{
entry section
critical section
exit section
remainder section
}while(1);
主要代码分析:
1.entry section用于在进入临界区时的等待
EnterCriticalSection(&my_section);
2.exit section用于离开临界区后的发送信号的工作,通知另外的线程可以进入临界区
LeaveCriticalSection(&my_section);
四、实践结果
基本数据:
源程序代码行数 完成实践投入的总时间 资料查阅时间 编程调试时间 源程序文件
193 0.2小时 0.1小时 0.1小时 ex3.cpp
测试数据设计:
“ex3.dat”文件内容如下:
0 1
1 1
2 1
3 1
4 1
测试结果分析:
运行结果图如下所示:
Now, We begin to read thread Information to thread_info array
I am thread 0 , I am doing 00000th step
I am thread 1 , I am doing 00000th step
Now the random number is 22413 ; and accnt1+accnt2 = 00000
I am thread 2 , I am doing 00000th step
Now the random number is 17802 ; and accnt1+accnt2 = 00000
I am thread 3 , I am doing 00000th step
Now the random number is 5286 ; and accnt1+accnt2 = 00000
I am thread 4 , I am doing 00000th step
Now the random number is 23304 ; and accnt1+accnt2 = 00000
I am thread 0 , I am doing 00001th step
Now the random number is 12270 ; and accnt1+accnt2 = 00000
I am thread 1 , I am doing 00001th step
Now the random number is 12170 ; and accnt1+accnt2 = 00000
I am thread 2 , I am doing 00001th step
Now the random number is 4729 ; and accnt1+accnt2 = 00000
I am thread 3 , I am doing 00001th step
Now the random number is 28247 ; and accnt1+accnt2 = 00000
I am thread 4 , I am doing 00001th step
Now the random number is 3819 ; and accnt1+accnt2 = 00000
I am thread 0 , I am doing 00002th step
Now the random number is 2578 ; and accnt1+accnt2 = 00000
I am thread 1 , I am doing 00002th step
Now the random number is 21931 ; and accnt1+accnt2 = 00000
I am thread 2 , I am doing 00002th step
Now the random number is 170 ; and accnt1+accnt2 = 00000
I am thread 3 , I am doing 00002th step
Now the random number is 18300 ; and accnt1+accnt2 = 00000
I am thread 4 , I am doing 00002th step
Now the random number is 2054 ; and accnt1+accnt2 = 00000
I am thread 0 , I am doing 00003th step
Now the random number is 538 ; and accnt1+accnt2 = 00000
I am thread 1 , I am doing 00003th step
Now the random number is 12469 ; and accnt1+accnt2 = 00000
I am thread 2 , I am doing 00003th step
Now the random number is 7825 ; and accnt1+accnt2 = 00000
I am thread 3 , I am doing 00003th step
Now the random number is 14181 ; and accnt1+accnt2 = 00000
I am thread 4 , I am doing 00003th step
Now the random number is 5984 ; and accnt1+accnt2 = 00000
I am thread 0 , I am doing 00004th step
Now the random number is 17150 ; and accnt1+accnt2 = 00000
I am thread 1 , I am doing 00004th step
Now the random number is 15529 ; and accnt1+accnt2 = 00000
At last of thread 0 accnt1+accnt2 = 00000
I am thread 2 , I am doing 00004th step
Now the random number is 31878 ; and accnt1+accnt2 = 00000
At last of thread 1 accnt1+accnt2 = 00000
I am thread 3 , I am doing 00004th step
Now the random number is 3842 ; and accnt1+accnt2 = 00000
At last of thread 2 accnt1+accnt2 = 00000
I am thread 4 , I am doing 00004th step
Now the random number is 5953 ; and accnt1+accnt2 = 00000
At last of thread 3 accnt1+accnt2 = 00000
Now the random number is 23968 ; and accnt1+accnt2 = 00000
At last of thread 4 accnt1+accnt2 = 00000
All threads have finished Operating.
Press any key to finish this Program.
程序运行过程中,线程1或线程2向accnt1中借款,一定延时后向accnt2中还款,总额accnt均为0,程序运行结果完全正确。
五、实践体会
使用临界区变量解决临界区问题实现起来比软件方法简单明了,并且可以应用到多进程的情况之中,通过这次实验我基本了解了临界区变量的使用方法和作用,其实,解决临界区问题的方法相当的多,从中选取一种合适的是要很多经验积累的。
六、参考文献
1、MSDN
附:源程序代码
#include <windows.h>
#include <conio.h>
#include <stdlib.h>
#include <fstream.h>
#include <stdio.h>
#include <time.h>
#define INTE_PER_SEC 500
#define MAX_THREAD_NUM 64
#define RIGHT_VERSION TRUE
#define WRONG_VERSION FALSE
CRITICAL_SECTION my_section;
struct ThreadInfo
{
int serial;
double delay;
};
/*volatile*/ int accnt1 = 0;
/*volatile*/ int accnt2 = 0;
/*volatile*/ int accnt;
void account( char* file,BOOL version);
void acc_right(void* p);
void acc_wrong(void* p);
////////////////////////////////////////////////////////
// main function
////////////////////////////////////////////////////////
int main( int agrc, char* argv[] )
{
char ch;
while ( TRUE )
{
// Clear screen
system( "cls" );
// display prompt info
printf("*********************************************\n");
printf(" 1.Start the right version(with the using of CRITICAL_SECTION)\n");
printf(" 2.Start the wrong version(without any algorithm of synchronization)\n");
printf(" 3.Exit to Windows\n");
printf("*********************************************\n");
printf("Input your choice(1 、2 or 3): ");
// if the number inputed is error, retry!
do
{
ch = (char)_getch();
}while ( ch != '1' && ch != '2'&& ch != '3');
system ( "cls" );
if ( ch == '1')
account("ex3.dat",RIGHT_VERSION);
else if (ch =='2')
account("ex3.dat",WRONG_VERSION);
else if ( ch == '3')
return 0;
printf("\nPress any key to finish this Program. \n");
_getch();
} //end while
} //end main
void account( char* file,BOOL version)
{
DWORD n_thread = 0;
DWORD thread_ID;
DWORD wait_for_all;
// Tread Object Array
HANDLE h_Thread[MAX_THREAD_NUM];
ThreadInfo thread_info[MAX_THREAD_NUM];
ifstream inFile;
inFile.open(file); //open file
printf( "Now, We begin to read thread Information to thread_info array \n\n" );
while ( inFile )
{
// read every thread info
inFile>>thread_info[n_thread].serial;
inFile>>thread_info[n_thread++].delay;
inFile.get();
} //end while
// initialize the data
srand((unsigned)time(NULL));
accnt1=0;
accnt2=0;
// Create all thread
if (version==RIGHT_VERSION)
{
InitializeCriticalSection(&my_section); //init critical section
for ( int i = 0; i < (int)(n_thread); i++)
{
// Create a thread
h_Thread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(acc_right), &thread_info[i], 0, &thread_ID);
} //end for
} else
{
for ( int i = 0; i < (int)(n_thread); i++)
{
// Create a thread
h_Thread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(acc_wrong), &thread_info[i], 0, &thread_ID);
} //end for
}
// Create thread
// waiting all thread will been finished
wait_for_all = WaitForMultipleObjects(n_thread,h_Thread,TRUE, -1);
printf("All threads have finished Operating.\n");
}// end account
void acc_right(void* p)
{
DWORD m_delay;
int m_serial;
int tmp1 , tmp2, rand_num;
int counter = 0;
//get info from para
m_serial = ((ThreadInfo*) (p)) -> serial;
m_delay = (DWORD) (((ThreadInfo*)(p)) -> delay*INTE_PER_SEC);
do
{
EnterCriticalSection(&my_section);
//begin critical_section
printf("I am thread %d , I am doing %05dth step\n",m_serial,counter);
tmp1 = accnt1;
tmp2 = accnt2;
rand_num = rand();
accnt1 = tmp1 - rand_num;
Sleep(m_delay);
accnt2 = tmp2 + rand_num;
accnt = accnt1 + accnt2;
//critical_section end
LeaveCriticalSection(&my_section);
counter++;
printf("Now the random number is %d ; and accnt1+accnt2 = %05d\n\n",rand_num,accnt);
} while (counter<5);
printf("At last of thread %d accnt1+accnt2 = %05d\n",m_serial,accnt);
} //end acc_right
void acc_wrong(void* p)
{
DWORD m_delay;
int m_serial;
int tmp1 , tmp2, rand_num;
int counter = 0;
//get info from para
m_serial = ((ThreadInfo*) (p)) -> serial;
m_delay = (DWORD) (((ThreadInfo*)(p)) -> delay*INTE_PER_SEC);
do
{
//begin critical_section
printf("I am thread %d , I am doing %05dth step\n",m_serial,counter);
tmp1 = accnt1;
tmp2 = accnt2;
rand_num = rand();
accnt1 = tmp1 - rand_num;
Sleep(m_delay);
accnt2 = tmp2 + rand_num;
accnt = accnt1 + accnt2;
//critical_section end
counter++;
printf("Now the random number is %d ; and accnt1+accnt2 = %05d\n\n",rand_num,accnt);
} while (counter<5);
printf("At last of thread %d accnt1+accnt2 = %05d\n",m_serial,accnt);
} //end acc_wrong
任务四 同步对象解决有限缓冲区问题
一、基本信息
实践题目:同步对象解决有限缓冲区问题
二、实践内容简要描述
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -