最近,有一课下作业要求我们使用互斥量或者信号量来解决线程的同步问题(男女浴室问题),没办法,学渣嘛,自己就上网找答案咯,可是搜了N多发现,他们写的基本都是错的(要么线程没控制好,要么产生死锁)。无奈.png,只能自己写写咯。话不多少先把任务贴上去。

任务要求:

男女共浴(或过桥问题)(引自 AST《现代操作系统》 3th, P98)。
1. 假设一个大学为了卖弄其政治上的正确性,准备把美国最高法院的信条“平等但隔
离其本身就是不平等”既运用在种族上也运用在性别上,从而结束校园内长期使用
的浴室按性别隔离的做法。但是,为了迁就传统习惯,学校颁布法令:当有一个女
生在浴室里,那么其他女生可以进入,但是男生不行,反之亦然。在每个浴室的门
上有一个滑动指示符号,表示当前处于以下三种可能状态之一:
 空
 有女生
 有男生
用你偏好的程序设计语言编写下面过程(可以随意采用所希望的计数器和同步技
术):
woman_wants_to_enter
man_wants_to_enter
woman_leaves
man_leaves

思路:

首先,我们先读懂题意,例如,当浴室开始营业时,第一个到达的是女生,那么女生这个性别就获得了该浴室的所有权,那么对于线程来说,那么这个女生线程就获得了锁,那么其他女生到达浴室门口时亦可以进去。男生到达浴室门口时,必须阻塞。等到最后一个女生洗完澡并且出来时,男生才可以进去。

接触过读者写者、生产者消费者的问题的我们应该可以轻松想到,解决这个问题需要两个共享变量来统计男女人数。(没有接触过以上的问题,这个设计难以下手)。我们把这两个共享变量命名为ManNum,WomanNum。然后我们就需要利用这个两个共享变量来进行同步操作了,问题是对共享变量的操作,我们要使用什么?答案是,我们得用互斥量或者信号量。但我本人更喜欢利用信号量来解决互斥问题。除此之外,我们不应该忽略一个的就是性别锁,它能控制浴室同时只能被一种性别访问。因此,解决这个问题,首先我得使用三个信号量(当然,互斥量也可以)。

设置好三个信号量,这三个信号量分别为mutex(性别互斥锁),mutex_man(对ManNum的操作互斥锁),mutex_woman(对WomanNum的操作互斥锁)。

下面我们就应该对这些信号量进行pv操作了。整个设计关键操作如下(以男生线程为例):

P(mutex_man) //对共享变量的互斥操作,只能允许一个男生线程对其进行操作。
ManNum++
if(ManNum==1){ //第一个男生到达,那么他就要担负起抢占性别锁的任务P(mutex)  //对性别锁进行P操作,抢占性别锁,如果抢占失败则被阻塞,等待女生线程的唤醒。
}
V(mutex_man)//如果抢到了锁,就允许其他男生进入洗澡...P(mutex_man)//对共享变量的互斥操作,只能允许一个男生线程对其进行操作。
ManNum--     //男生洗完澡离开时的操作if(ManNum==0){//最后一个男生离开时,就要释放性别锁,从而能让女生进入浴室
V(mutex) //释放性别锁
}
V(mutex_man)

源码:

/**************************************************
*功能:在多线程环境下解决线程互斥与同步
*环境:Ubuntu16.04
*
*输入:第一个参数 男生线程数 第二个参数 女生线程数
*输出:男生、女生对浴室(共享资源)的同步与互斥控制。
*制作:Macmanboy
*完成的题目要求:基础部分(已完成)
*测试:程序没有出现死锁与饥饿。
*版本:2017/12/10
*
***************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<semaphore.h>
#include<pthread.h>
#include<time.h>
sem_t mutex;//互斥量,性别互斥锁,男女不能同时待在浴室
sem_t mutex_man;//互斥量,不得两个男生同时进入、离开浴室
sem_t mutex_woman;//互斥量,不得两个女生同时进入、离开浴室
sem_t empty;//浴室容量
int ManNum=0;//男生人数
int WomanNum=0;//女生人数
void Shower()//洗澡操作,包括所用时间
{int ShowerTime=rand()%3+1;sleep(ShowerTime);}
void *ManComeIn(void *rank)
{//模拟男生陆陆续续到来,到来的时间随机int my_rank=(int)rank;int ComeInTime=rand()%5+1;printf("\033[1;37m");//打印白色printf("男生%d:在%d秒后即将到达浴室!\n",my_rank,ComeInTime);sleep(ComeInTime);//男生线程睡眠,模拟到达浴室门口的时间是随机的printf("\033[1;37m");//打印白色printf("男生%d:到达浴室!\n",my_rank);sem_wait(&mutex_man);//不能两个男生同时进来ManNum++; //男生进入人数if(ManNum==1){sem_wait(&mutex);//禁止女生进来}sem_post(&mutex_man);//其他男生可以进来sem_wait(&empty);//浴室容量减1操作printf("\033[1;37m");//打印白色printf("男生%d:进入浴室洗澡!\n",my_rank);Shower();//模拟洗澡,洗澡时间长度随机sem_wait(&mutex_man);//不能两个男生同时离开ManNum--;if(ManNum==0){//最后一个男生离开sem_post(&mutex);  //释放浴室性别使用锁}sem_post(&mutex_man);//其他男生可以离开sem_post(&empty);//浴室容量加1printf("\033[1;37m");printf("男生%d:离开浴室!\n",my_rank);}
void *WomanComeIn(void *rank)
{//模拟女生陆陆续续到来,到来的时间随机int my_rank=(int)rank;int ComeInTime=rand()%5+1;printf("                               \033[1;31m");printf("女生%d:在%d秒后即将到达浴室!\n",my_rank,ComeInTime);sleep(ComeInTime);//女生线程睡眠,模拟到达浴室门口的时间是随机的printf("                               \033[1;31m");printf("女生%d:到达浴室!\n",my_rank);sem_wait(&mutex_woman);//不能两个女生同时进来WomanNum++;//女生浴室人数if(WomanNum==1){sem_wait(&mutex);//禁止男生进来}sem_post(&mutex_woman);//其他女生可以进来sem_wait(&empty);//printf("                               \033[1;31m");printf("女生%d:进入浴室洗澡!\n",my_rank);Shower();sem_wait(&mutex_woman);WomanNum--;//女生浴室人数if(WomanNum==0){sem_post(&mutex); // }sem_post(&mutex_woman);//其他女生可以离开sem_post(&empty);//浴室容量加1printf("                               \033[1;31m");printf("女生%d:离开浴室!\n",my_rank);}
int main(int argc,char *argv[]){
srand(time(NULL));//设置时间种子
sem_init(&mutex,1,1);
sem_init(&mutex_man,0,1);
sem_init(&mutex_woman,0,1);
sem_init(&empty,0,5);
int num_man=strtol(argv[1],NULL,10);
int num_woman=strtol(argv[2],NULL,10);
pthread_t *man_handles;
pthread_t *woman_handles;
man_handles=malloc(num_man*sizeof(pthread_t));
woman_handles=malloc(num_woman*sizeof(pthread_t));
for(int i=0;i<num_man;i++)//创建男生线程
pthread_create(&man_handles[i],NULL,ManComeIn,(void*)i);
for(int i=0;i<num_woman;i++)//创建女生线程
pthread_create(&woman_handles[i],NULL,WomanComeIn,(void*)i);
for(int i=0;i<num_man;i++)//
pthread_join(man_handles[i],NULL);
for(int i=0;i<num_woman;i++)//
pthread_join(woman_handles[i],NULL);
sem_destroy(&mutex);
sem_destroy(&mutex_man);
sem_destroy(&mutex_woman);
sem_destroy(&empty);
free(man_handles);
free(woman_handles);
return 0;
}

测试结果:

当然,我们也可以做下面的扩展:

2. 可做下列功能的扩展:
1) 设置一个同性别学生洗澡的时间段,当过此时间段后,想进去浴室的同性别的
学生不允许进入。等全部出浴室后,优先让另一性别的学生进浴室洗澡。
2) 设置浴室的最多容纳人数
扩展部分的代码,作者整理完后就贴上。

如何用信号量与互斥量解决男女共浴(或过桥问题)相关推荐

  1. 信号量解决男女共浴问题

    任务要求: 男女共浴(或过桥问题)(引自 AST<现代操作系统> 3th, P98). 1. 假设一个大学为了卖弄其政治上的正确性,准备把美国最高法院的信条"平等但隔 离其本身就 ...

  2. Linux多线程实践(5) --Posix信号量与互斥量解决生产者消费者问题

    Posix信号量 Posix 信号量 有名信号量 无名信号量 sem_open sem_init sem_close sem_destroy sem_unlink sem_wait sem_post ...

  3. FreeRTOS的信号量和互斥量

    1. 理解如下,言简意赅的说,信号量解决同步,互斥量解决竞争. 信号量用于同步,主要任务间和中断间同步:互斥量用于互锁,用于保护同时只能有一个任务访问的资源,为资源上一把锁. 互斥量具有优先级继承,信 ...

  4. 哲学家就餐问题--信号量和互斥量预防死锁

    哲学家就餐问题可以采取预防死锁的方案,就是使用互斥量和信号量锁定资源. 互斥量: 对资源进行锁定的意思就是说,当一个哲学家使用叉子的时候,他首先要先把叉子锁定,然后,拿起来.这个时候如果别的哲学家也来 ...

  5. freertos 创建互斥量_FreeRTOS的信号量和互斥量

    1. 理解如下,言简意赅的说,信号量解决同步,互斥量解决竞争. 信号量用于同步,主要任务间和中断间同步:互斥量用于互锁,用于保护同时只能有一个任务访问的资源,为资源上一把锁. 互斥量具有优先级继承,信 ...

  6. 【Windows】线程漫谈——线程同步之信号量和互斥量

    本系列意在记录Windwos线程的相关知识点,包括线程基础.线程调度.线程同步.TLS.线程池等 信号量内核对象 信号量内核对象用来进行资源计数,它包含一个使用计数.最大资源数.当前资源计数.最大资源 ...

  7. LINUX线程同步:原子操作、锁、二元信号量、信号量、互斥量、临界区、读写锁、条件变量等

    注:摘自<程序员的自我修养>相关章节. 原子操作 共享数据(全局变量或堆变量)的自增(++)操作在多线程环境下会出现错误是因为这个操作(一条c语句)被编译为汇编代码后不止一条指令,因此在执 ...

  8. 任务间同步 | 信号量、互斥量和事件集

    本文分享自中移OneOS公众号<任务间同步>. 多个任务操作同一块代码区域,这块代码就称为临界区,如果任何时刻最多只允许一个任务去使用临界区,那么多个任务就需要互斥的访问.当一个任务占用此 ...

  9. linux操作系统之信号量、互斥量在进程间的同步、文件锁

    (1)信号量:进化版的互斥量 多个线程间对某个对象的部分数据进行共享,使用互斥锁是没有办法实现的,只能将整个数据对象锁住.这样虽然达到了多线程操作数据共享的目的,却导致线程并发性下降. 信号量:相对折 ...

最新文章

  1. 独家 | 每个业务分析专家应具备的9个关键技能
  2. 为什么我强烈推荐你学习 Java ?(必看)
  3. android gridview 中图片大小不一,android – Gridview及其图像不适合所有屏幕大小
  4. testid oracle vue,Vue 组件单元测试究竟测试什么?
  5. about EnableEventValidation 这是什么意思,欢迎指点一下,谢谢
  6. 基于syslog+logstash+elasticSearch+redis日志分析系统实现
  7. 新一代来袭︱不只是舒适,简直是享受,Google公司用的腰靠,到底有什么秘密?...
  8. [html] link标签的属性media有哪些值?都有什么作用?
  9. 单片机8×8点阵显示简单汉字的程序_干货 | 浅析单片机制作贪吃蛇游戏
  10. RECT JS 由浅入深
  11. 数据库每日一题 2020.05.09
  12. buck变换器设计matlab_[Fundamental of Power Electronics]-PART I-6.变换器电路-6.2 变换器简单罗列 - Yangswear...
  13. Linq(筛选与排序)
  14. matlab2c使用c++实现matlab函数系列教程-det函数
  15. PHP比较两个时间戳相差天时分秒
  16. sql 二进制文件的导入导出
  17. 开发者工具——web前端助手
  18. DirectShow之音频录制Wav
  19. L314 单音节词读音规则(二)-元音字母发音规则
  20. [ACMMM2018]BeautyGAN: Instance-level Facial Makeup Transfer with DeepGenerative Adversarial Network

热门文章

  1. 前端面试知识点整理(持续更新)
  2. cmd命令行中无pip命令的解决办法
  3. android mp3播放器学习之预备知识1:activity
  4. 浪潮服务器虚拟化分区,浪潮服务器–虚拟化解决方案.ppt
  5. T 客汇盘点:2017 年备受关注的 20 家企业级服务公司
  6. 计算机一级基础知识替换,2018年计算机一级考试WPS辅导知识:WPS查找和替换的使用...
  7. C语言FOR语句实现的重复控制结构
  8. 问题事件名称: BEX
  9. 腾飞的野三坡,打造国际旅游黄金水岸
  10. 实训项目 数字迷宫小游戏