实验四 信号量
使用二值信号量解决多线程售票系统数据错误问题
- 实现代码
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
int ticketAmout = 2; // 票的数量: 全局变量
sem_t mutex; // 定义信号量mutex
void* ticketAgent(void* arg){
sem_wait(&mutex); // 执⾏P操作
int t = ticketAmout;
if (t > 0){
printf("One ticket sold\n");
t--;
}else{
printf("Ticket sold out\n");
}
ticketAmout = t;
sem_post(&mutex); // 执⾏V操作
pthread_exit(0);
}
int main(int argc, char const* agrv[]){
pthread_t ticketAgent_tid[2];
sem_init(&mutex, 0, 1); // 初始化信号量
for(int i = 0; i < 2; i++){
pthread_create(ticketAgent_tid+i, NULL, ticketAgent, NULL);
}
for (int i = 0; i < 2; i++){
pthread_join(ticketAgent_tid[i], NULL);
}
sleep(1);
printf("The left ticket is %d\n", ticketAmout);
sem_destroy(&mutex); // 销毁信号量
return 0;
}
一般信号量的观察
-
1.没有使用信号量的情况下:
-
该题示意图如下:
-
我们现在有5个线程,但是只有两份资源可⽤;我们通过信号量去模拟这⼀种情况
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
void* cars(void* argc){
printf("(%u) I INTEND to pass the fork\n",pthread_self());
sleep(1);
printf("(%u) I am AT the fork\n",pthread_self());
sleep(1);
printf("(%u) I have PASSED the fork\n",pthread_self());
sleep(1);
pthread_exit(0);
}
int main(int argc, char const* agrv[]){
pthread_t tid[5];
for (int i = 0; i < 5; i++){
pthread_create(tid+i, NULL, cars, NULL);
}
for (int i = 0; i < 5; i++){
pthread_join(tid[i], NULL);
}
return 0;
}
- 当我们的线程中没有使用sleep(1);方法时
可以发现这是我们的线程是一个一个通过的,好像没有什么问题。这是因为我们的线程太少以及我们的线程执行速度太快导致的。所以我们需要使用sleep方法将检查的速度降下来才能看到现象
-
添加了sleep方法后的现象
这样我们可以发现既然这5个线程同时都在fork,这和我们规定的只有2条线路(资源)可用的原理是违背的,他的这种运行逻辑是不正确的 -
皆下面我们将这个问题加上信号量
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
sem_t road;
void* cars(void* argc){
printf("(%u) I INTEND to pass the fork\n",pthread_self());
sleep(1);
sem_wait(&road); // 执⾏P操作
printf("(%u) I am AT the fork\n",pthread_self());
sleep(1);
printf("(%u) I have PASSED the fork\n",pthread_self());
sleep(1);
sem_post(&road); // 执⾏V操作
pthread_exit(0);
}
int main(int argc, char const* agrv[]){
pthread_t tid[5];
sem_init(&road, 0, 2);
for (int i = 0; i < 5; i++){
pthread_create(tid+i, NULL, cars, NULL);
}
for (int i = 0; i < 5; i++){
pthread_join(tid[i], NULL);
}
sem_destroy(&road);
return 0;
}