【操作系统核心编程】大四的编程作业留底

 邹老师布置了五个Task,不过自己时间不够,尽量做吧。感觉着实很有用,所以打算先记录下来。

1. 进程打开进程 

2.  多线程

3.  线程互斥

4.  多线程操作数组

5.  多线程模型

 

笔者按:

使用windows对象解决临界区问题:
方式有:
windows执行体对象:
  • 互斥对象:mutex 实现一个资源同一时刻只能被一个线程使用
  • 事件对象:event 限制并发访问的线程数
  • 信号量对象:semaphore
windows子系统对象:
  • 临界区 critical section,同一进程内对于临界区的访问是互斥的

『临界区windows子系统对象,不是内核对象,只能用于同步单个进程中的线程,要注意跟信号量相区别。』

 

/*
    task 2
    应用Peterson算法解决临界区问题  协作线程——兄弟问题
    
    利用Peterson算法,实现线程间的互斥。
        boolean flag[2];//初值false
        int turn;
        do{
           flag[i]:=true;
           turn=j;
           while(flag[j] and turn=j);
               临界区;
           flag[i]=false;
               剩余区;
          }while(1);
*/

#include <windows.h>
#include <conio.h>
#include <stdlib.h>
#include <fstream>  //for Dev C++  VC use #include <fstream.h>
#include <stdio.h>

#define INTE_PER_SEC  1000
#define MAX_THREAD_NUM  64

struct ThreadInfo
{
	int	serial;
	double	delay;
};

volatile  int accnt1 = 0; /*  in the memory */
volatile  int accnt2 = 0;
volatile  bool flag[2] = {0,0};
volatile int turn;
void account( char* file);
void acc(void* p);

////////////////////////////////////////////////////////
// main fuction
////////////////////////////////////////////////////////

int main( int agrc, char* argv[] )
{
	char ch;

	while ( TRUE )
	{
		// Cleare screen
		system( "cls" );

		// display prompt info
		printf("*********************************************\n");
		printf("       1.Start test\n");
		printf("       2.Exit to Windows\n");
		printf("*********************************************\n");
		printf("Input your choice(1or2): ");

		// if the number inputed is error, retry!
		do{
			ch = (char)_getch();
		}while( ch != '1' && ch != '2');

		system ( "cls" );
		if ( ch == '1')
			account( (char*)"sm6.dat");
		else if ( ch == '2')
			return 0;
		printf("\nPress any key to finish this Program. \nThank you test this Proggram!\n");
		_getch();
	} //end while
} //end main

void account( char* file)
{
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];

std::ifstream  inFile;  //for Dev C++   VC use ifstream  inFile;
inFile.open(file,std::ifstream::in);		//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

// Create all thread
for( int i = 0; i < (int)(n_thread); i++)
{
	// Create a thread
    	h_Thread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(acc), &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(void* p)
{
	DWORD m_delay;
	int m_serial;
	int rand_num, accnt,counter = 0;;

//get info froam para

	m_serial = ((ThreadInfo*) (p)) -> serial;
	m_delay  = (DWORD) (((ThreadInfo*)(p)) -> delay*INTE_PER_SEC);
	srand( (unsigned)((ThreadInfo*)(p)) -> delay );
	do {
		printf("I am thread  %d , I am doing  %05dth step\n",m_serial,counter);
		rand_num = rand();
		/* printf("rand_num =  %05d \n",rand_num); */
		//Sleep(m_delay);
        int i=m_serial;
        flag[i-1] = true;
        int j = (m_serial==2?1:2);
        turn = j;
        while(flag[m_serial-1] and turn==j)
            j=j;
//begin critical_section
		accnt1 = accnt1 - rand_num;
		Sleep(m_delay);
		accnt2 = accnt2 + rand_num;
		accnt = accnt1 + accnt2;
//critical_section  end
        flag[i] = false;
		counter++;
	} while ( (accnt == 0) && (counter<10));
	printf("Now accnt1+accnt2 =  %05d\n",accnt);
} //end acc

  

 

/*
    task 3
*/
#include <windows.h>
#include <conio.h>
#include <stdlib.h>
#include <fstream>  //for Dev C++  VC use #include <fstream.h>
#include <stdio.h>

#define INTE_PER_SEC  1000
#define MAX_THREAD_NUM  64

struct ThreadInfo
{
	int	serial;
	double	delay;
};

volatile  int accnt1 = 0; /*  in the memory */
volatile  int accnt2 = 0;

CRITICAL_SECTION  BRO_Add;

void account( char* file);
void acc(void* p);

////////////////////////////////////////////////////////
// main fuction
////////////////////////////////////////////////////////

int main( int agrc, char* argv[] )
{
	char ch;

	while ( TRUE )
	{
		// Cleare screen
		system( "cls" );

		// display prompt info
		printf("*********************************************\n");
		printf("       1.Start test\n");
		printf("       2.Exit to Windows\n");
		printf("*********************************************\n");
		printf("Input your choice(1or2): ");

		// if the number inputed is error, retry!
		do{
			ch = (char)_getch();
		}while( ch != '1' && ch != '2');

		system ( "cls" );
		if ( ch == '1')
			account( (char*)"sm6.dat");
		else if ( ch == '2')
			return 0;
		printf("\nPress any key to finish this Program. \nThank you test this Proggram!\n");
		_getch();
	} //end while
} //end main

void account( char* file)
{
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];

std::ifstream  inFile;  //for Dev C++   VC use ifstream  inFile;
inFile.open(file,std::ifstream::in);		//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
InitializeCriticalSection(&BRO_Add);
// Create all thread
for( int i = 0; i < (int)(n_thread); i++)
{
	// Create a thread
    	h_Thread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(acc), &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(void* p)
{
	DWORD m_delay;
	int m_serial;
	int rand_num, accnt,counter = 0;;

//get info froam para

	m_serial = ((ThreadInfo*) (p)) -> serial;
	m_delay  = (DWORD) (((ThreadInfo*)(p)) -> delay*INTE_PER_SEC);
	srand( (unsigned)((ThreadInfo*)(p)) -> delay );
	do {
		printf("I am thread  %d , I am doing  %05dth step\n",m_serial,counter);
		rand_num = rand();
        EnterCriticalSection(&BRO_Add);
//begin critical_section
		accnt1 = accnt1 - rand_num;
		Sleep(m_delay);
		accnt2 = accnt2 + rand_num;
		accnt = accnt1 + accnt2;
//critical_section  end
        LeaveCriticalSection( &BRO_Add );
		counter++;
	} while ( (accnt == 0) && (counter<10));
	printf("Now accnt1+accnt2 =  %05d\n",accnt);
} 

  

 

/*
    task 4
    windows 核心编程:有限缓冲区问题
    测试数据:4.dat
    生产者消费者算法:
        生产者:计算一定范围内素数并将其放入 prime 队列(数组实现的)
        消费者:将素数取出并打印出来。
    临界区和事件对象解决线程独占资源问题。
    Reference:
        CreateEvent function: https://msdn.microsoft.com/en-us/library/ms682396(VS.85).aspx
        WaitForSingleObject function: https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx
*/

#include <windows.h>
#include <conio.h>
#include <stdlib.h>
#include <fstream>
#include <stdio.h>

#define MAX_THREAD_NUM  64
using namespace std;
struct ThreadInfo
{
	int	serial;
	char entity;
	int from;
	int to;
};

int prime[9];
int count = 0;

volatile int putArea=0;

HANDLE h_full;  
HANDLE h_empty; 
CRITICAL_SECTION  criticalSection;

void control( char* file);
void consumerThread(void* p);
void producerThread(void* p);

////////////////////////////////////////////////////////
// main fuction
////////////////////////////////////////////////////////

int main( int agrc, char* argv[] )
{
	char ch;

	for(int i = 0;i < 9; i++)
	{
		prime[i] = 0;
	}

	while ( TRUE )
	{
		// Cleare screen
		system( "cls" );

		// display prompt info
		printf("*********************************************\n");
		printf("       1.Start test\n");
		printf("       2.Exit to Windows\n");
		printf("*********************************************\n");
		printf("Input your choice(1or2): ");
		
		// if the number inputed is error, retry!
		do{
			ch = (char)_getch(); 
		}while( ch != '1' && ch != '2');

		system ( "cls" );
		if ( ch == '1')
			control("4.dat");
		else if ( ch == '2')
			return 0;
		printf("\nPress any key to finish this Program. \nThank you test this Proggram!\n");
		_getch();
	} //end while
} //end main

void  control( char* file)
{
DWORD n_thread = 0;
DWORD thread_ID;
DWORD wait_for_all;

InitializeCriticalSection(&criticalSection); 

// Tread Object Array

HANDLE h_Thread[MAX_THREAD_NUM];
ThreadInfo  thread_info[MAX_THREAD_NUM];

h_full = CreateEvent(NULL,TRUE,TRUE,"full_event");
h_empty = CreateEvent(NULL,TRUE,TRUE,"empty_event");

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].entity;
	inFile>>thread_info[n_thread].from;
	inFile>>thread_info[n_thread++].to;
	inFile.get();
} //end while

// Create all thread
for( int i = 0; i < (int)(n_thread); i++)
{	
	if(thread_info[i].entity == 'D')// Create a reader thread
	{
		h_Thread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(consumerThread), &thread_info[i], 0, &thread_ID);
	}
	else
	{
		h_Thread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(producerThread), &thread_info[i], 0, &thread_ID);
	}
    	
} //end for
	
// 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 consumerThread(void* p) 
{
	
	int m_count;
	int m_serial;

	int i = 0;
	int readcount=0;

	m_serial = ((ThreadInfo*) (p)) -> serial;
	m_count  = ((ThreadInfo*)(p)) -> from;

	do {
		WaitForSingleObject(h_full,-1); 		
		EnterCriticalSection(&criticalSection);
		while(!prime[i])
		{
			i=(i+1)%9;
		}
		printf("Consumer thread %d reads %d from postion %d.\n",m_serial,prime[i],i);
		prime[i] = 0;
		count--;
		readcount++;
		LeaveCriticalSection(&criticalSection);  
		SetEvent(h_empty); 
		Sleep(1000);
	} while ( readcount<(int)m_count); 
	return;
} 

void producerThread(void* p)
{
	int m_from;
	int m_to;
	int m_serial;

	m_serial = ((ThreadInfo*) (p)) -> serial;
	m_from  = ((ThreadInfo*)(p)) -> from;
	m_to  = ((ThreadInfo*)(p)) -> to;
	int i = 0;

	for(int j = (int)m_from;j < (int)m_to;j++)
	{
		
		if(j==1) continue;
		int k;
		for(k = 2;k <= j/2;k++)
		{
			if(j % k == 0) break;
		}
		if(k < j/2 +1) continue;
		
		if(count == 9) break;
		WaitForSingleObject(h_empty,-1);  
		EnterCriticalSection(&criticalSection);;  
		prime[putArea%9] = j;
		printf("Producer thread %d writes %d to the %d postion.\n",m_serial,j,putArea%9);
		putArea++;
		count++;
		LeaveCriticalSection(&criticalSection); 
		SetEvent(h_full); 
		Sleep(1000);
	}
	return;
} 

  

原文链接:http://www.cnblogs.com/learn-to-rock/p/5894682.html

posted @ 2016-09-22 00:02  LandFlow  阅读(331)  评论(0编辑  收藏  举报