多線程實現銀行家算法

實驗要求
1.測試數據隨機產生。不可手工輸入;
2.線程所需的全部資源一次全部給予
3.線程釋放資源時分多次釋放,一次釋放一種所有資源。
提出第2和第3點要求的原因是模擬進程的調度不容易,所以以多個線程請求資源來模擬一個進程多次請求資源

程序流程圖
在這裏插入圖片描述
實驗心得
第一次使用條件變量,對條件變量cond的使用更加熟悉了。
爲了防止出現臨界區內因條件不足不程序無法繼續運行下去,而又因爲是在臨界區,所以代碼運行的互斥的,所以條件就永遠不能滿足導致程序一直無法運行下去。所以出現了條件變量cond。
pthread_cond_wait(&cond, &mutex);掛起等待條件cond的調用線程,釋放鎖,以便其他線程使用。
pthread_cond_broadcast(&cond);恢復執行先前因在條件cond上執行pthread_cond_wait而掛起的那幾個線程。

實驗代碼

#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>

#define Maxpronum 1000
#define m 4 /*一共有4種資源*/

int pronum = 0; //當前運行線程數

int threadFinished[Maxpronum];
int mark[Maxpronum];
int Allocation[Maxpronum][m];
int Need[Maxpronum][m];
int Avaliable[m];
int Max[Maxpronum][m];

pthread_mutex_t mutex;
pthread_cond_t cond;

void init() //數據初始化
{
	for (int i = 0; i < Maxpronum; i++)	
	{
		mark[i] = 0for (int j = 0; j < m; j++)
		{
			Allocation[i][j] = 0;
			Need[i][j] = 0;
			Max[i][j] = 0;
		}
	}
	for (int i = 0; i < m; i++)
	{
		Avaliable[i] = 100;
	}
}
int safe(int id) //安全性算法
{
	int Work[4];
	int Finish[Maxpronum];
	int safecount = 0;
	int count;
	int n = Maxpronum;
	int threadSafeSequence[Maxpronum];
	for (int i = 0; i < m; i++)
		Work[i] = Avaliable[i];
	for (int i = 0; i < m; i++)
		Finish[i] = 0;
	for (int k = 0; k < n; k++) //嘗試得到安全序列
	{
		for (int i = 0; i < n; i++)
		{
			count = 0;
			for (int j = 0; j < m; j++)
			{
				if (Need[i][j] <= Work[j])
				count++;
			}
			if (count == m)
			{
				for (int j = 0; j < m; j++)
				{
					Work[j] = Work[j] + Allocation[i][j];
				}
				if (mark[i] == 1 && Finish[i] == 0)
				{
					Finish[i] = 1;		
					threadSafeSequence[safecount++] = i;
				}
			}
		}
	}
	count = 0;
	for (int i = 0; i < n; i++)
	{
		if (mark[i] == 1)
		count++;
	}
	if (count == pronum)
	{
		printf("安全序列爲:");
		for (int i = 0; i < safecount; i++)
			printf(" %d", threadSafeSequence[i]);
		printf("\n");
		return 1;
	}
	else
	{
		return 0;
	}
}

int Banker(int id, int Request[]) //銀資源分配算法
{
	for (int i = 0; i < m; i++)
	{
		if (Request[i] > Avaliable[i])
		{
			printf("線程%d所需的資源不足,等待!\n", id);
			return 0;
		}
	}
	for (int i = 0; i < m; i++)
	{
		if (Request[i] > Need[id][i] + Allocation[id][i])
		{
			printf("線程%d對資源的申請量大於它說明的最大值\n", id);
			return 0;
		}
	}
	for (int i = 0; i < m; i++) //嘗試分配資源
	{
		Avaliable[i] = Avaliable[i] - Request[i];
		Allocation[id][i] = Allocation[id][i] + Request[i];
		Need[id][i] = Need[id][i] - Request[i];
	}
	mark[id] = 1;
	pronum++;
	if (!safe(id)) //分配後不存在安全序列則回收資源
	{
		for (int i = 0; i < m; i++)
		{
			Avaliable[i] = Avaliable[i] + Request[i];
			Allocation[id][i] = Allocation[id][i] - Request[i];
			Need[id][i] = Need[id][i] + Request[i];
		}
		mark[id] = 0;
		pronum--;
		printf("線程%d沒通過安全性算法,不批准獲得資源!\n", id);
		return 0; /*不安全*/
	}
	return 1; /*安全*/
}

void *threadprocess(void *arg)
{
	while (1)
	{
		int id = *(int *)arg;
		int Request[m];
		for (int i = 0; i < m; i++)
		{
			Request[i] = Need[id][i] = Max[id][i] = rand() % 30; //隨機生成需要的資源數
		}
		printf("線程%d請求:", id);
		for (int i = 0; i < m; i++)
			printf("%d ", Request[i]);
		printf("\n");
		pthread_mutex_lock(&mutex);
		while (Banker(id, Request) == 0) //若不滿足銀行家算法則等待
		{
			pthread_cond_wait(&cond, &mutex);
		}
		for (int i = 0; i < m; i++)
		{
			Need[id][i] = 0;
		}
		pthread_cond_broadcast(&cond);
		pthread_mutex_unlock(&mutex);

		printf("線程%d已得到全部所需的資源\n", id);
		sleep(1);
		printf("線程%d開始釋放資源\n", id);
		for (int i = 0; i < m; i++) //每隔一段時間釋放一種資源
		{
			sleep(rand() % 3);
			pthread_mutex_lock(&mutex);
			Avaliable[i] = Avaliable[i] + Request[i];
			Max[id][i] = 0;
			Allocation[id][i] = 0;
			if (i == m - 1)
			{
				mark[id] = 0;
				pronum--;
			}
			pthread_cond_broadcast(&cond);
			pthread_mutex_unlock(&mutex);
		}
		printf("線程%d已經釋放全部資源\n", id);
		if (rand() % 2 == 0)
			break;
	}
	pthread_exit(NULL);
}
int main()
{
	init();
	pthread_t tid[Maxpronum];
	pthread_mutex_init(&mutex, NULL);
	pthread_cond_init(&cond, NULL);
	int M[Maxpronum];
	int i = 0;
	while (1)
	{
		if (rand() % 2 == 0)
		{
			while (mark[i] == 1)
			i = i + 1;
			M[i] = i;
			pthread_create(&tid[i], NULL, threadprocess, (void *)&M[i]);
			sleep(rand() % 3);
		}
		i = i + 1;
		if (i == Maxpronum - 1)
			i = 0;
	}
	for (int i = 0; i < Maxpronum; i++)
	pthread_join(tid[i], NULL);
	return 0;
}

實驗結果截圖
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章