實驗要求
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] = 0;
for (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;
}
實驗結果截圖