?? 設計報告.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 + -