操作系统--进程锁算法1(两个进程的锁)
对于实验环境,利用CLion并通过cmake工具链接到pthread动态库1,使得最终能从Linux的vi编辑器中解脱(成功在win环境下运行),致谢傻狗老公配的cmake工具@zorchp
一些定义:
临界区: 进程互斥就是为了让有共享变量的代码段安全,所以将对共享变量操作的部分称为临界区。
进程锁的尝试1:
p0:do{while(turn ==1);//临界区代码turn=1;//其他代码}while(1);p1:do{while(turn ==0);//临界区代码turn=0;//其他代码}while(1);
这样做的好处是:
1.实现了进程的有限等待:等待时间有限
2.实现了进程的互斥性,对于临界区代码,两个进程一定不会一起执行,因为一进入程序判断的就是turn变量,turn标志了该是轮到哪个进程执行就轮到谁执行
缺点与不足:
没有实现进程的进展性原则:
该原则要求:
(1)临界区为空闲的时候,一个要求进入临界区的进程应该立即进入
(2)临界区被某一进程占有时,其他想要进临界区的进程应该处于等待状态
(3)当一个进程离开时,应该允许其他等待进入临界区的进程进入
分析如下:
p0从临界区出来之后,置turn=1,轮到p1执行,p1从临界区出来之后,将turn置0,轮到p0执行,但有一种可能是,p0把turn放在1之后,执行下面的代码,但是此时还没执行完下面的代码,但是轮到p0占有临界区,此时,违反了(1),临界区处于空闲,p1无法进入临界区
演示实验:
#include<stdio.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
int turn;
pthread_t pid1;
pthread_t pid2;_Noreturn void* fun1(void *p) {//pthread_join(pid1,NULL);do {while (turn == 2);printf("0\n");printf("i am the process 1\n");printf("1\n");turn = 2;sleep(3);} while (1);
}_Noreturn void* fun2(void *p)
{//pthread_join(pid1,NULL);
do{while(turn ==1);printf("2\n");printf("i am the process 2\n");printf("3\n");turn=1;sleep(100);}while(1);}
int main(void)
{turn=1;int a=pthread_create(&pid1,NULL,fun1,NULL);int b=pthread_create(&pid2,NULL,fun2,NULL);pthread_join(pid1,NULL);pthread_join(pid2,NULL);//这里是为了阻塞,可能主线进程直接没了,但是还没轮到pid1,pid2执行printf("4\n");if(a==0&&b==0)printf("success\n");printf("bye\n");
结果:
0
i am the process 1
1
2
i am the process 2
3
0
i am the process 1
1
在执行到这里之后就一直不出结果了,的确出现了上述现象
为了对这种现象进行改进,我们只需要让需要进入的置为1,不进入的置为0即可。
进程锁的尝试2:
bool status[2]={0,0};
p0:do{while(status[1]==1);//pos1status[0]=1;//临界区代码status[0]=0;//其他代码}while(1);p1:do{while(status[0]==1);status[1]=1;//临界区代码status[1]=0;//其他代码}while(1);
但是这个又有可能发生破坏互斥性,就是两个进程同时运行临界区,多处理机的话初始就同时运行了;
单处理机的话,刚进入一个while,在pos1跳转,肺泡了,
只要不在pos1跳就没事
尝试3:综合以上结果修改算法:(这个算法不是Dekker算法)
bool status[2]={0,0};
int turn =1
p0:do{while(status[1]==1);//pos1if(turn==0){ status[0]=1;//临界区代码turn=1;status[0]=0;//其他代码}}while(1);p1:do{while(status[0]==1);if(turn==1){ status[1]=1;//临界区代码turn=0;status[1]=0;//其他代码}}while(1);
事实证明:
经过联合修改之后的程序是没有问题的,不仅实现了互斥效果,而且很好的维持了进展性。使得进程可以交替进行。
实验代码:
#include<stdio.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
int turn;
pthread_t pid1;
pthread_t pid2;
int count=10000;
int a[2];
_Noreturn void* fun1(void *p) {//pthread_join(pid1,NULL);do {while (a[0]==1);if(turn == 1){a[1]=1;printf("0\n");count--;printf("i am the process 1 :%d\n",count);printf("1\n");a[1]=0;turn = 2;sleep(3);}} while (1);
}_Noreturn void* fun2(void *p)
{//pthread_join(pid1,NULL);
do{while(a[1] ==1);if(turn ==2){a[0]=1;printf("2\n");count--;printf("i am the process 2 :%d\n",count);printf("3\n");turn=1;a[0]=0;sleep(3);}}while(1);}
int main(void)
{turn=1;a[0]=0;a[1]=0;int a=pthread_create(&pid1,NULL,fun1,NULL);int b=pthread_create(&pid2,NULL,fun2,NULL);pthread_join(pid1,NULL);pthread_join(pid2,NULL);printf("4\n");if(a==0&&b==0)printf("success\n");printf("bye\n");}
输出结果
0
i am the process 1 :9999
1
2
i am the process 2 :9998
3
0
i am the process 1 :9997
1
2
i am the process 2 :9996
3
0
i am the process 1 :9995
1
2
i am the process 2 :9994
3
0
i am the process 1 :9993
1
2
i am the process 2 :9992
3
0
i am the process 1 :9991
1
2
i am the process 2 :9990
3
0
i am the process 1 :9989
1
2
i am the process 2 :9988
3
0
i am the process 1 :9987
1
2
i am the process 2 :9986
3
0
i am the process 1 :9985
1
2
i am the process 2 :9984
3
0
i am the process 1 :9983
1
2
i am the process 2 :9982
3
0
i am the process 1 :9981
1
2
i am the process 2 :9980
3
0
i am the process 1 :9979
1
2
i am the process 2 :9978
3
0
i am the process 1 :9977
1
2
i am the process 2 :9976
3
0
i am the process 1 :9975
1
2
i am the process 2 :9974
3
0
i am the process 1 :9973
1
3算法的证明与分析:
对于互斥性,turn变量很好的控制了这一点
对于可进展性:只要0进程从临界区中出来status[0]就变成0,如果没变的话,1进程运行不了,跳回来进程0的时候,status[0]一定变成0,这一句费不了多长时间,然后进程1立刻可以执行,如果进程1一直在其他代码那里运行,其status为0进程0也可以执行,也就是说利用松弛状态数组,和turn变量就可以保持互斥he可进展
对于等待有限性:
如果两个status都是1,才会出现死锁,但是,这个时候两个东西应该在临界区而不是循环等待,所以不会出现死锁。
https://zhuanlan.zhihu.com/p/128519905 ↩︎
操作系统--进程锁算法1(两个进程的锁)相关推荐
- Linux高级进程编程———在任意两个进程间传递文件描述符:使用 sendmsg 和 recvmsg 实现
进程间传递打开的文件描述符,并不是传递文件描述符的值.那么在传递时究竟传递了什么?我们要先搞明白这个问题. 1.文件描述符 文件描述符的值与文件没有任何联系,只是该文件在进程中的一个标识,所以同一文件 ...
- (王道408考研操作系统)第二章进程管理-第一节3:进程控制(配合Linux讲解)
文章目录 一:如何实现进程控制 二:进程控制原语 (1)进程创建 A:概述 B:补充-Linux中的创建进程操作 ①:fork() ②:fork()相关问题 (2)进程终止 A:概述 B:补充-僵尸进 ...
- Linux中fork()系统调用创建两个子进程
使用系统调用fork()创建两个子进程: #include <stdio.h> #include <unistd.h>int main(){int fpid = fork(); ...
- MySQL 锁的相关知识 | lock与latch、锁的类型、简谈MVCC、锁算法、死锁、锁升级
文章目录 lock与latch 锁的类型 MVCC 一致性非锁定读(快照读) 一致性锁定读(当前读) 锁算法 死锁 锁升级 lock与latch 在了解数据库锁之前,首先就要区分开 lock 和 la ...
- 操作系统实验二——时间片轮转调度算法(RR算法)(新进程放队首和队尾两种C++实现)
情况介绍 基本原理 系统将所有就绪进程按照FCFS的原则,排成一个队列依次调度. 把CPU分配给队首进程,执行一个时间片(10-100ms). 时间片用完后,系统计时器发出时钟中断,该进程将被剥夺CP ...
- 操作系统c语言两个进程制约且互斥,电大计算机本科《操作系统》作业2及答案...
A.低级进程通信 B.高级进程通信 C.共享内存方式 D.管道文件方式 27. 系统出现死锁的原因是( ). A.计算机系统发生了重大故障 B.有多个封锁的进程同时存在 C.若干进程因竞争资源而无休止 ...
- 【Linux操作系统】Linux进程状态和两个特殊进程
文章目录 一.一套普适性的进程状态理论 1.运行 2.阻塞 3.挂起 二.一套具体的Linux进程状态 1.R-运行 2.S-睡眠 3.T-暂停 5.t-被追踪 三.僵尸进程和孤儿进程 1.僵尸进程 ...
- 操作系统春招面试复习之:进程管理
一.进程 1.1 多道程序设计 允许多个程序同时进入内存并运行,提高CPU的利用率,目的是提高系统效率 a图内存中有四个程序,串行执行,因为这里只有一个程序计数器. 当有了多道程序技术之后就得到了b图 ...
- 【操作系统学习笔记】—— 【二】进程、线程、死锁
本文参考: JavaGuide 王道考研-操作系统 CS-Notes 文章目录 一.进程的概念.组成.特征 1. 概念 2. 进程的组成 PCB 程序段 数据段 3. 进程的特征 二.进程的状态 三. ...
最新文章
- python正则取字符串日期_python 正则表达式获取字符串中所有的日期和时间
- js中的正则表达式入门
- 自动生成用户名,密码的方法
- 常用开发技巧系列(三)
- SSD成就了《扩散性百万亚瑟王》
- 大话设计模式Python实现-简单工厂模式
- GCC和MSVC的INITIALIZER的实现
- 如何选择一款优秀的儿童读写台灯?
- 获取mysql所有用户权限_查看MYSQL数据库中所有用户及拥有权限
- 史上最大内存!曝iPhone 14 Pro系列运行内存将增至8GB
- wxPython--学习笔记
- PPT中的文字怎么填充为图片?学会这个方法少走不少弯路
- 布客·ApacheCN 编程/大数据/数据科学/人工智能学习资源 2020.1
- 2020中国数据智能产业图谱1.0版发布丨数据猿产业全景图
- VSCode中值得推荐的常用的33个高效前端插件「效率篇」(二)
- 如何定位crach问题
- 百度回应文心一言文生图功能争议
- Android基础知识【项目实训-实现二级导航“今日活动”及读取数据库】【5】
- Python+Selenium自动化测试脚本(入门)
- Hypervisor---虚拟化技术简易说明