操作系统--进程锁算法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
#include 
#include 
#include 
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);
    //pos1
     status[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);
    //pos1
    if(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
#include 
#include 
#include 
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,才会出现死锁,但是,这个时候两个东西应该在临界区而不是循环等待,所以不会出现死锁。


  1. https://zhuanlan.zhihu.com/p/128519905 ↩︎

你可能感兴趣的:(操作系统,操作系统,新cp)