多线程模拟客户实现银行家算法_操作系统
1. 主题:
多线程、防止竞态条件和死锁避免。
2. 目的:
多线程程序来实现银行家算法
3. 要求:
多个客户请求和释放银行资源,只有仍能使系统处于安全状态,银行家才会允许请求,会让系统处于非安全状态的请求都将被拒绝。
银行家:
银行家分析来自n个客户对m个资源类型的请求,首先银行家将使用一下数据结构来跟踪资源:
客户:
创建n个客户线程,以便请求和释放资源:
客户不断的循环:请求在释放随机数量的资源,客户的资源请求不超过他们的数组Need的相应值。如果一个请求满足安全算法,那么银行家将会允许他,如果一个请求不能将系统保持在安全状态,那么银行家将拒绝他,请求和释放资源的原型如下:
request_resources()函数:
release_resources()函数
互斥锁:
采用互斥锁来控制访问,以便防止竞争条件。
具体上锁的位置可以理解为,只要是对共享资源的操作就加锁,操作完成就解锁。
有些特殊的输出也可以对其进行加锁,这样可以保证是原子输出,不会被其他线程横插一杠,打乱我们应有的输出,到时候调试都不好调试。
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <omp.h>
#include <pthread.h>
#include <sys/time.h>
#include <time.h>
#include <semaphore.h>
#define Num_Cus 5 //客户数量
#define Num_Res 3 //资源数量
//每种资源可用实例数量
int ava[Num_Res] ;//= {3,3,2};
//每个进程的最大需求
int max[Num_Cus][Num_Res] = { {7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3} };
//每个进程现在分配的每种资源类型的实例数量
int allocation[Num_Cus][Num_Res] = { {0,1,0},{2,0,0},{3,0,2},{2,1,1},{0,0,2} };
//max-allocation
int Need[Num_Cus][Num_Res];
//记录安全序列
int arr[Num_Cus];
pthread_mutex_t mutex;
pthread_cond_t cond;
int isless(int a[],int b[],int n){ //判断a数组是不是全部小于b数组
int flag = 1;
for(int i=0;i<n;i++){
if(a[i]>b[i]){
flag = 0;
break;
}
}
return flag;
}
int issafe(){
int flag = 0; //判断是否是安全状态
int num = 0;
int Work[Num_Res];
int Finish[Num_Cus];
memset(Finish,0,sizeof(int)*Num_Cus);//初始化Finish数组
//Finish[customer_num] = 1;
for(int i=0;i<Num_Res;i++){ //初始化Work数组
Work[i] = ava[i];
}
int i = 0;
int x = 0;
for(i=0;i<Num_Cus;i++){
if(Finish[i]==0&&isless(Need[i],Work,Num_Res)){
arr[x] = i;
x++;
//printf("i: %d\n",i);
//printf("work:");
for(int j=0;j<Num_Res;j++){
Work[j] += allocation[i][j];
//printf("%d ",Work[j]);
}
//printf("need:");
// for(int j=0;j<Num_Res;j++){
// //printf("%d ",Need[i][j]);
// }
//printf("\n");
Finish[i] = 1;
i=-1;
}
}
num=0;
//printf("Finish数组: ");
for(int j=0;j<Num_Cus;j++){
if(Finish[j] == 1){
num++;
}
}
if(num == Num_Cus)
flag = 1; //系统处于安全状态
else
flag = 0;
return flag;
}
int request_resources(int customer_num,int request[]){//用户请求资源
int flag = 0; //判断是否请求资源成功 0表示未成功,1表示成功;
if(isless(request,Need[customer_num],Num_Res)){
if(isless(request,ava,Num_Res)){
for(int i=0;i<Num_Res;i++){ //假设分配
ava[i] -= request[i];
allocation[customer_num][i] += request[i];
Need[customer_num][i] -= request[i];
}
if(!issafe()){ //如果不安全,返回原状态,申请资源失败
for(int i=0;i<Num_Res;i++){
ava[i] += request[i];
allocation[customer_num][i] -= request[i];
Need[customer_num][i] += request[i];
}
flag = 0;
printf("客户%d没通过安全性算法,不批准获得资源!\n", customer_num);
}
else{
printf("客户%d已得到所需的资源\n", customer_num);
printf("安全序列为 : < ");
for(int i=0;i<Num_Cus;i++){
printf("%d ",arr[i]);
}
printf(">\n"); //申请资源成功,返回1
flag = 1;
}
}
else{
printf("没有客户%d足够的资源 等着吧\n",customer_num);
}
}
else{
flag = 0;
printf("你不诚心呀,%d号小伙子!\n",customer_num);
}
return flag;
}
int isrelease(int customer_num){
int flag = 1;
for(int i=0;i<Num_Res;i++){
if(Need[customer_num][i]>0){
flag=1;
break;
}
}
return flag;
}
int release_resources(int customer_num){//用户释放资源
printf("客户%d开始释放资源\n", customer_num);
int flag = 0;
for(int i=0;i<Num_Res;i++){
ava[i] += allocation[customer_num][i];
allocation[customer_num][i] = 0;
}
printf("客户%d已经释放全部资源\n", customer_num);
flag = 1;
return flag;
}
void get_random(int customer_num,int request[]){
for(int i=0;i<Num_Res;i++){
request[i] = (rand()%(Need[customer_num][i]+1));
}
}
//摘录
void usingthread(int customer_num)
{
while (1)
{
int request[Num_Res];
pthread_mutex_lock(&mutex);
get_random(customer_num,request);
pthread_mutex_unlock(&mutex);
pthread_mutex_lock(&mutex);
printf("客户%d请求:", customer_num);
for (int i = 0; i < Num_Res; i++)
printf("%d ", request[i]);
printf("\n");
pthread_mutex_unlock(&mutex);
pthread_mutex_lock(&mutex); //上锁,开始请求资源
while (request_resources(customer_num, request) == 0){ //若不满足银行家算法则等待
pthread_cond_wait(&cond, &mutex); //挂起等待直到条件满足 条件变量cond与互斥锁mutex一起用。
}
pthread_cond_broadcast(&cond); //激活所有等待线程,区别signal(激活一个)
pthread_mutex_unlock(&mutex); //解锁
//printf("客户%d已得到所需的资源\n", customer_num);
sleep(1);
if(isrelease(customer_num)){
pthread_mutex_lock(&mutex);
release_resources(customer_num);
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
}
if (rand() % 2 == 0)
break;
}
pthread_exit(NULL);
}
int main(int argc,char* argv[]){
for(int i=1;i<argc;i++){
ava[i] = atoi(argv[i]);
//printf("%d ",ava[i]);
}
int request[Num_Res] = {1,0,2};
int cus_num = 1;
for(int i=0;i<Num_Cus;i++){
for(int j=0;j<Num_Res;j++){
Need[i][j] = max[i][j] - allocation[i][j];
}
}
pthread_t tid[Num_Cus];
pthread_attr_t attr[Num_Cus];
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
for(int i=0;i<Num_Cus;i++){
pthread_attr_init(&attr[i]);
}
for(int i=0;i<Num_Cus;i++){
pthread_create(&tid[i], &attr[i], usingthread, i);
}
for(int i=0;i<Num_Cus;i++){
pthread_join(tid[i],NULL);
}
return 0;
}