linux下经典同步问题,Linux经典同步问题2-哲学家就餐问题

2023-10-28 12:50

本文主要是介绍linux下经典同步问题,Linux经典同步问题2-哲学家就餐问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

死锁

死锁是 《操作系统原理》课程中的1个很重要的概念, 它描述的是多个进程因竞争资源而造成的1种僵局 ,若无外力作用 ,这些进程将永远不能再向前推进。产生死锁的原因主要有2点: 1是竞争资源 ; 2是进程推进顺序不当。

1、哲学家就餐问题

一张圆桌上坐着 5 名哲学家,桌子上每两个哲学家之间摆了一根叉子,桌子的中间是一碗米饭,如图所示,并且假如按照下面方式进行编号,那么第i为科学家,它的左手边筷子是i,右手边筷子是(i+1)%5。

0ae3445068ab5732b9182960cfb9ed98.png

一般性描述:在实际的计算机问题中,缺乏餐叉可以类比为缺乏共享资源。一种常用的计算机技术是资源加锁,用来保证在某个时刻,资源只能被一个程序或一段代码访问。当一个程序想要使用的资源已经被另一个程序锁定,它就等待资源解锁。当多个程序涉及到加锁的资源时,在某些情况下就有可能发生死锁。例如,某个程序需要访问两个文件,当两个这样的程序各锁了一个文件,那它们都在等待对方解锁另一个文件,而这永远不会发生。

1、最直观错误的解法1

这里要开5个线程,每个哲学家对应一个线程。最开始想到的办法是:每个哲学家先拿起左叉子,再拿起右叉子。并定义互斥信号量数组chopstick[5] = {1,1,1,1,1}用于对5根叉子的互斥访问

伪代码:

#define N 5//哲学家数目

semaphore chopstick[5] = {1,1,1,1,1}//信号量数组,信号量初始化为1互斥访问每根叉子,对叉子进行互斥量保护

void philosopher(int i)//哲学家编号,从0-4

{

while(ture){

think();//想事情,独立,根本不需要保护

down(&chopstick[i]);//拿左手边筷子

down(&chopstick[(i+1)%N]);//拿右手边筷子

eat();

up(&chopstick[i]);//放回左手边筷子

up(&chopstick[(i+1)%N]);//放回右手边筷子

}

}

通过相当于通过信号量保护共享资源,每个线程需要两份,所以每次需要获取两个信号量。但是上面可能出现死锁,那就是5个哲学家同时拿起左边筷子,那么将没有人可以拿到右边快子,于是产生死锁。

2、信号量机制解决哲学家就餐问题

先来两个结论:

(1)系统中有N个并发进程。 若规定每个进程需要申请2个某类资源, 则当系统提供N+1个同类资源时,无论采用何种方式申请资源, 一定不会发生死锁。分析:N+1个资源被N个进程竞争,由抽屉原理可知,则至少存在一个进程获2个以上的同类资源。这就是前面提到的哲学家就餐问题中5个哲学家提供6支筷子时一定不会发生死锁的原因。

(2)系统中有N个并发进程。 若规定每个进程需要申请R个某类资源, 则当系统提供K=N*(R-1)+1个同类资源时,无论采用何种方式申请使用,一定不会发生死锁。分析:在最坏的情况下,每个进程都申请到R-1个同类资源, 此时它们均阻塞。 试想若系统再追加一个同类资源, 则N 个进程中必有一个进程获得R个资源,死锁解除。

结合以上分析,哲学家就餐问题可以被抽象描述为:系统中有5个并发进程, 规定每个进程需要申请2个某类资源。 若系统提供5个该类资源, 在保证一定不会产生死锁的前提下,最多允许多少个进程并发执行?假设允许N个进程, 将R=2,K=5带入上述公式, 有N*(2-1)+1=5所以N=4。也就意味着,如果在任何时刻系统最多允许4个进程并发执行, 则一定不会发生死锁。 大多数哲学家就餐问题死锁阻止算法都是基于这个结论。 增加一个信号量,控制最多有4个进程并发执行

#define N 5//哲学家数目

semaphore chopstick[5] = {1,1,1,1,1};//信号量数组,信号量初始化为1互斥访问每根叉子,对叉子进行互斥量保护

semaphore mutex = 4;//控制哲学家数量

void philosopher(int i)//哲学家编号,从0-4

{

while(ture){

think();//想事情,独立,根本不需要保护

down(&mutex);//

down(&chopstick[i]);//拿左手边筷子

down(&chopstick[(i+1)%N]);//拿右手边筷子

eat();

up(&chopstick[i]);//放回左手边筷子

up(&chopstick[(i+1)%N]);//放回右手边筷子

up(&mutex);//

}

}

3、用附加规则解决哲学家进餐问题

对哲学家顺序编号,要求奇数号哲学家先抓左边的叉子,然后再抓他右边的叉子,而偶数号哲学家刚好相反。这样的话就总会有一名哲学家可以顺利获得两支筷子开始进餐。此方法的本质是通过附加规则,让哲学家按照一定的顺序请求临界资源——筷子。这样的话,在资源分配图中就不会出现环路,破坏了死锁生的必要条件之一:“环路等待”条件,从而有效地预防了死锁的产生。

#define N 5

semaphore chopstick[5] = {1,1,1,1,1};

void philosopher(int i){

while(TRUE){

think();

if(i%2==1){//奇数号哲学家

down(&chopstick[i]);//先左边

down(&chopstick[(i+1)%N);//后右边

}else{//偶数号哲学家

down(&chopstick[(i+1)%N]);//先右边

down(&chopstick[i]);//后左边

}

eat();

up(&chopstick[i]);

up(&chopstick[(i+1)%N];

}

4、仅当一个哲学家左右两边的叉子都可用时才允许他抓起叉子

哲学家要么不拿,要么就拿两把叉子。那么哲学家就有三种状态:思考状态不用叉子、饥饿状态在等待左右叉子、吃饭状态正在使用叉子。

#define N 5

#define LEFT (i-1+N)%N;//i左邻居编号

#define RIGHT (i+1)%N;//i右邻居编号

#define THINKING 0 //思考状态

#define HUNGRY 1 //试图拿起叉子

#define EATTING 2 //进餐

int state[N];//记录哲学家状态

semaphore mutex = 1;//临界区,仅仅允许一个进入

semaphore s[N] = {0,0,0,0,0};//每个哲学家一个信号量,初始化为0

void philosopher(i)

{

think(i);

take_forks(i); //吃饭前先等待两只叉子

eatting();

put_forks(i); //放下叉子,查看左右邻居是否两只叉子都空闲,如果空闲提醒邻居拿起叉子

}

void take_forks(i)

{

down(&mutex)

state[i] = HUNGRY; //代表当前哲学家正在等待叉子

test_take_left_right_forks(i); //尝试获取两把叉子

up(&mutex); //离开临界区

down(&s[i]); //如果拿不到叉子就阻塞

}

void test_take_left_right_forks(i)

{

if(state[i] == HUNGRY && state[LEFT] != EATTING && state[RIGTH] != EATTING)

{

state[i] = EATTING; //用EATTING代表当前哲学家能拿到两只叉子

up(&s[i]); //如果能够拿到两只叉子,唤醒当前线程

}

}

void putdown(i)

{

P(mutex)

state[i] = THINKING; //代表当前不需要叉子

test_take_left_right_forks(LEFT);

test_take_left_right_forks(RIGHT);

V(mutex);

}

void thinking(i)

{

P(mutex);

state[i] = THINKING;

V(mutex);

}

这篇关于linux下经典同步问题,Linux经典同步问题2-哲学家就餐问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/293338

相关文章

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

linux-基础知识3

打包和压缩 zip 安装zip软件包 yum -y install zip unzip 压缩打包命令: zip -q -r -d -u 压缩包文件名 目录和文件名列表 -q:不显示命令执行过程-r:递归处理,打包各级子目录和文件-u:把文件增加/替换到压缩包中-d:从压缩包中删除指定的文件 解压:unzip 压缩包名 打包文件 把压缩包从服务器下载到本地 把压缩包上传到服务器(zip

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

购买磨轮平衡机时应该注意什么问题和技巧

在购买磨轮平衡机时,您应该注意以下几个关键点: 平衡精度 平衡精度是衡量平衡机性能的核心指标,直接影响到不平衡量的检测与校准的准确性,从而决定磨轮的振动和噪声水平。高精度的平衡机能显著减少振动和噪声,提高磨削加工的精度。 转速范围 宽广的转速范围意味着平衡机能够处理更多种类的磨轮,适应不同的工作条件和规格要求。 振动监测能力 振动监测能力是评估平衡机性能的重要因素。通过传感器实时监

缓存雪崩问题

缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。 解决方案: 1、使用锁进行控制 2、对同一类型信息的key设置不同的过期时间 3、缓存预热 1. 什么是缓存雪崩 缓存雪崩是指在短时间内,大量缓存数据同时失效,导致所有请求直接涌向数据库,瞬间增加数据库的负载压力,可能导致数据库性能下降甚至崩溃。这种情况往往发生在缓存中大量 k