银行系统模拟:使用信号量和 P、V 操作实现优先级服务
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h>
#define M 5 // 柜员数 #define N 20 // 最大用户数
// 用户类型 #define PUBLIC 0 // 对公用户 #define VIP 1 // VIP用户 #define NORMAL 2 // 普通用户
sem_t sem_customer; // 顾客信号量 sem_t sem_window[M]; // 柜员信号量 pthread_t tid[N]; // 线程ID数组
int window_status[M] = {0}; // 柜员状态数组 int customer_count = 0; // 顾客数量 int customer_num = 0; // 顾客号码
// 顾客结构体 typedef struct { int id; // 顾客号码 int type; // 顾客类型 } customer_t;
// 顾客取号 void get_customer_number(customer_t* customer) { sem_wait(&sem_customer); // 等待顾客信号量 customer->id = ++customer_num; // 顾客号码递增 printf('Customer %d got number %d. ', customer->id, customer_num); switch (customer->type) { case PUBLIC: printf('Type: Public\n'); break; case VIP: printf('Type: VIP\n'); break; case NORMAL: printf('Type: Normal\n'); break; } }
// 顾客排队 void wait_in_line(customer_t customer) { int i, window_id; int priority[M] = {0}; // 每个窗口的优先级 int min_priority = 100; // 最小优先级 for (i = 0; i < M; i++) { sem_getvalue(&sem_window[i], &window_status[i]); // 获取柜员信号量的值 if (window_status[i] == 0) // 如果柜员空闲 { priority[i] = 0; // 优先级为0 } else { switch (customer.type) // 根据顾客类型设置优先级 { case PUBLIC: priority[i] = 3; break; case VIP: priority[i] = 2; break; case NORMAL: priority[i] = 1; break; } } if (priority[i] < min_priority) // 找到最小优先级 { min_priority = priority[i]; window_id = i; } } sem_wait(&sem_window[window_id]); // 等待柜员信号量 window_status[window_id] = 1; // 将柜员状态设置为忙碌 printf('Customer %d is served by window %d. \n', customer.id, window_id+1); sleep(3); // 模拟柜员服务时间 window_status[window_id] = 0; // 将柜员状态设置为空闲 sem_post(&sem_window[window_id]); // 释放柜员信号量 }
// 对公用户线程函数 void* public_customer(void* arg) { customer_t customer; customer.type = PUBLIC; while (1) { get_customer_number(&customer); wait_in_line(customer); } return NULL; }
// VIP用户线程函数 void* vip_customer(void* arg) { customer_t customer; customer.type = VIP; while (1) { get_customer_number(&customer); wait_in_line(customer); } return NULL; }
// 普通用户线程函数 void* normal_customer(void* arg) { customer_t customer; customer.type = NORMAL; while (1) { get_customer_number(&customer); wait_in_line(customer); } return NULL; }
int main() { int i;
sem_init(&sem_customer, 0, N); // 初始化顾客信号量
for (i = 0; i < M; i++)
{
sem_init(&sem_window[i], 0, 1); // 初始化柜员信号量
}
// 创建对公用户、VIP用户、普通用户线程
pthread_create(&tid[0], NULL, public_customer, NULL);
pthread_create(&tid[1], NULL, vip_customer, NULL);
pthread_create(&tid[2], NULL, normal_customer, NULL);
// 等待线程结束
for (i = 0; i < 3; i++)
{
pthread_join(tid[i], NULL);
}
// 销毁信号量
sem_destroy(&sem_customer);
for (i = 0; i < M; i++)
{
sem_destroy(&sem_window[i]);
}
return 0;
}
原文地址: https://www.cveoy.top/t/topic/nSKL 著作权归作者所有。请勿转载和采集!