当前位置: 首页 > news >正文

信号量(上)实验

实验1:解决订票终端的临界区管理
订票终端是解决冲突问题,所以信号量的值是1
在这里插入图片描述

#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(intargc, 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;
}

在这里插入图片描述
不进行V操作,造成死锁
在这里插入图片描述

第二个进程无限busy waiting。

在这里插入图片描述

实验2:一般信号量观察
我们现在有5个线程,但是只有两份资源可用;我们通过信号量去模拟这一种情况,将信号量的值初始化为2

我们先来看一种情况,当没有信号量进行控制的时候

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
void* cars(void* argc){
printf("(%lu) I INTEND to pass the fork\n",pthread_self());
sleep(1);
printf("(%lu) I am AT the fork\n",pthread_self());
sleep(1);
printf("(%lu) 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;
}

在这里插入图片描述可以看到每五个进程都同时占用了临界区的通道,也就是临界区同时运行了五个进程,这个是有问题的

我们梳理一下逻辑,input是进入程序,at fork 和 passed fork是分支产生(冲突或者同步),所以at 和 passed这段区域是临界区,代码如下:

#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;}

每个fork执行流一次可以跑两个分支,两分支同步。
同一时间段内只有两个能进入到fork里面,执行完成只有,另外两个才能进入。
在这里插入图片描述

http://www.lryc.cn/news/15638.html

相关文章:

  • 阿里5年,一个女工对软件测试的理解
  • 前端练习项目
  • sql复习(set运算符、高级子查询)
  • 整车电源的几种模式:OFF/ACC/RUN/CRANK
  • 踩了大坑:wordpress后台 无法将上传的文件移动至wp-content
  • page cache设计及实现
  • 使用seata来解决分布式事务
  • 推荐一款新的自动化测试框架:DrissionPage
  • MQ系列面试
  • 一句话设计模式2:原型模式
  • c++11特性与c++17特性
  • Redis02: Redis基础命令
  • MDK的HardFault硬件异常和NMI异常原因总结
  • 视频图像质量诊断
  • make、Makefile项目自动化构建工具
  • Linux系统之Uboot、Kernel、Busybox思考之一
  • CCNP350-401学习笔记(401-450题)
  • 一文带你看透前端世界里的日期时间,对就是Date
  • 易基因|RRBS单碱基绘制580种动物的基因组规模DNA甲基化谱:Nature子刊
  • 面试官:能用JavaScript手写一个bind函数吗
  • 美国拟发布纽扣电池或硬币电池安全标准和通知要求ANSI C18. 3M
  • 双因素方差分析
  • [ vulhub漏洞复现篇 ] Drupal XSS漏洞 (CVE-2019-6341)
  • 「TCG 规范解读」第8章 TPM工作组 TPM 1.2中 SHA1的使用
  • 熵权法计算权重
  • redis实现用户签到,统计活跃用户,用户在线状态,用户留存率
  • MySQL中有多少种索引?索引的底层实现原理
  • LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解
  • 【Java闭关修炼】MyBatis-接口代理的方式实现Dao层
  • 2022年网络安全政策态势分析与2023年立法趋势