操作系統:進程同步演示

進程同步演示

一、實驗目的

• 深入掌握進程同步機制——信號量機制的應用;
• 掌握Windows編程中信號量機制的使用方法;
• 可進行簡單的信號量應用編程。

二、實驗工具

Windows系統 + VisuaStudio2019

三、實驗內容

1、複習教材上信號量機制的定義與應用,複習經典進程同步問題——生產者消費者問題及其同步方案;
2、驗證後附的參考代碼pc.cpp(生產者消費者問題),掌握Windows系統中信號量的定義與使用方法;
注意:
1)代碼中 生產者 和 消費者 所做的工作 用過程Producer和Consumer描述,並通過創建線程的方法創建3個生產者線程和1個消費者線程,具體創建方法:CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);其中第3個參數就是指定該線程所做的工作爲過程Producer;
2)問題中設置了三個信號量g_hMutex(用於互斥訪問臨界區buffer)、g_hFullSemaphore、g_hEmptySemaphore(用於控制同步的資源信號量),先聲明,再定義,最後使用。互斥信號量和資源信號量的定義方法不同:
g_hMutex = CreateMutex(NULL,FALSE,NULL); 互斥信號量最開始沒有指定針對那個資源
g_hFullSemaphore = CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,NULL); 其中第2和3個參數爲信號量的初始值和最大值
信號量的使用方法:WaitForSingleObject爲信號量的P操作,每對一個信號量執行該操作,則信號量值減1,並判斷減1後值是否仍大於等於0,如是則該操作成功,否則進程阻塞; ReleaseSemaphore爲信號量的V操作,每執行一次將該信號量的值加1,並起到喚醒作用。如:
WaitForSingleObject(g_hFullSemaphore,INFINITE);

ReleaseSemaphore(g_hEmptySemaphore,1,NULL);
ReleaseMutex(g_hMutex);

3、撰寫實驗報告,請在實驗報告中給出運行結果,並對程序功能進行分析,可截圖
代碼段

#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <iostream>

const unsigned short SIZE_OF_BUFFER = 10; //緩衝區長度 
unsigned short ProductID = 0; //產品號
unsigned short ConsumeID = 0; //將被消耗的產品號
unsigned short in = 0; //產品進緩衝區時的緩衝區下標
unsigned short out = 0; //產品出緩衝區時的緩衝區下標

int g_buffer[SIZE_OF_BUFFER]; //緩衝區是個循環隊列 
bool g_continue = true; //控制程序結束
HANDLE g_hMutex; //用於線程間的互斥 
HANDLE g_hFullSemaphore; //當緩衝區滿時迫使生產者等待
HANDLE g_hEmptySemaphore; //當緩衝區空時迫使消費者等待
DWORD WINAPI Producer(LPVOID); //生產者線程
DWORD WINAPI Consumer(LPVOID); //消費者線程

int main()
{
	//創建各個互斥信號  
	g_hMutex = CreateMutex(NULL, FALSE, NULL);
	g_hFullSemaphore = CreateSemaphore(NULL, SIZE_OF_BUFFER - 1, SIZE_OF_BUFFER - 1, NULL);
	g_hEmptySemaphore = CreateSemaphore(NULL, 0, SIZE_OF_BUFFER - 1, NULL);

	//調整下面的數值,可以發現,當生產者個數多於消費者個數時,  
	//生產速度快,生產者經常等待消費者;反之,消費者經常等待 
	const unsigned short PRODUCERS_COUNT = 3; //生產者的個數
	const unsigned short CONSUMERS_COUNT = 1; //消費者的個數 

	//總的線程數 
	const unsigned short THREADS_COUNT = PRODUCERS_COUNT + CONSUMERS_COUNT;
	HANDLE hThreads[THREADS_COUNT]; //各線程的handle  
	DWORD producerID[PRODUCERS_COUNT]; //生產者線程的標識符
	DWORD consumerID[CONSUMERS_COUNT]; //消費者線程的標識符  

	//創建生產者線程
	for (int i = 0; i < PRODUCERS_COUNT; ++i) {
		hThreads[i] = CreateThread(NULL, 0, Producer, NULL, 0, &producerID[i]);
		if (hThreads[i] == NULL) return -1;
	}
	//創建消費者線程 
	for (int i = 0; i < CONSUMERS_COUNT; ++i) {
		hThreads[PRODUCERS_COUNT + i] = CreateThread(NULL, 0, Consumer, NULL, 0, &consumerID[i]);
		if (hThreads[i] == NULL) return -1;
	}

	while (g_continue) {
		if (getchar()) { //按回車後終止程序運行  
			g_continue = false;
		}
	}

	return 0;
}
//生產一個產品。簡單模擬了一下,僅輸出新產品的ID號  
void Produce()
{
	std::cerr << "Producing " << ++ProductID << " ... ";
	std::cerr << "Succeed" << std::endl;
}

//把新生產的產品放入緩衝區  
void Append()
{
	std::cerr << "Appending a product ... ";
	g_buffer[in] = ProductID;
	in = (in + 1) % SIZE_OF_BUFFER;
	std::cerr << "Succeed" << std::endl;

	//輸出緩衝區當前的狀態  
	for (int i = 0; i < SIZE_OF_BUFFER; ++i) {
		std::cout << i << ": " << g_buffer[i];
		if (i == in) std::cout << " <-- 生產";
		if (i == out) std::cout << " <-- 消費";
		std::cout << std::endl;
	}
}

//從緩衝區中取出一個產品  
void Take()
{
	std::cerr << "Taking a product ... ";
	ConsumeID = g_buffer[out];
	out = (out + 1) % SIZE_OF_BUFFER;
	std::cerr << "Succeed" << std::endl;

	//輸出緩衝區當前的狀態  
	for (int i = 0; i < SIZE_OF_BUFFER; ++i) {
		std::cout << i << ": " << g_buffer[i];
		if (i == in) std::cout << " <-- 生產";
		if (i == out) std::cout << " <-- 消費";
		std::cout << std::endl;
	}
}

//消耗一個產品  
void Consume()
{
	std::cerr << "Consuming " << ConsumeID << " ... ";
	std::cerr << "Succeed" << std::endl;
}

//生產者  
DWORD WINAPI Producer(LPVOID lpPara)
{
	while (g_continue) {
		WaitForSingleObject(g_hFullSemaphore, INFINITE);
		WaitForSingleObject(g_hMutex, INFINITE);
		Produce();
		Append();
		Sleep(1500);
		ReleaseMutex(g_hMutex);
		ReleaseSemaphore(g_hEmptySemaphore, 1, NULL);
	}
	return 0;
}

//消費者
DWORD WINAPI Consumer(LPVOID lpPara)
{
	while (g_continue) {
		WaitForSingleObject(g_hEmptySemaphore, INFINITE);
		WaitForSingleObject(g_hMutex, INFINITE);
		Take();
		Consume();
		Sleep(1500);
		ReleaseMutex(g_hMutex);
		ReleaseSemaphore(g_hFullSemaphore, 1, NULL);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章