Peterson算法與Dekker算法解析


進來Bear正在學習鞏固並行的基礎知識,所以寫下這篇基礎的有關並行算法的文章。

在講述兩個算法之前,需要明確一些概念性的問題,

Race Condition(競爭條件),Situations  like  this,  where  two  or  more processes  are  reading or writing some shared data and the final result depends on who runs precisely when, are called race conditions.多個進程(線程)讀寫共享區域(共享文件、共享變量、共享內存等)時,最后的結果依賴於他們執行的相對時間。

Critical Regions(關鍵區域),That part of the program where the shared memory is accessed.在程序中,訪問共享內存的部分。

Mutual exclusion(互斥), that is, some way of making sure that if one process is using a shared  variable or file, the other processes will be excluded from doing the same thing.指在一個進程在使用共享區域時,防止另外的進程做同樣的事情。

同樣,需要四個條件來找到一個好的解決方案,實現進程(線程)之間的互斥:

Dekker算法與Peterson算法就是用來實現進程或者線程之間的互斥。

Dekker算法:(參考了百度百科上面的Dekker算法解析,還是挺易懂的)

Dekker算法可以用於控制兩個進程(線程)之間的同步,如下實現的功能就是專門用於線程的同步:

其中,flag[2]用來表示是否想要使用關鍵區,turn用來表示具有訪問權限的進程ID。(重點看注釋,通過注釋,挺好理解的喲~

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#define true 1
#define false 0
typedef int bool;
bool flag[2];
int turn;
void visit(int num)
{
        sleep(1);
        printf("P%d is visting\n",num);
}
void P0()
{
        while(true)
        {
                flag[0] = true;//P0想使用關鍵區。
                while(flag[1])//檢查P1是不是也想用?
                {
                        if(turn == 1)//如果P1想用,則查看P1是否具有訪問權限?
                        {
                                flag[0] = false;//如果有,則P0放棄。
                                while(turn == 1);//檢查turn是否屬於P1。
                                flag[0] = true;//P0想使用。
                        }
                }
                visit(0); //訪問Critical Partition。
                turn = 1; //訪問完成,將權限給P1。
                flag[0] = false;//P0結束使用。
        }
}
void P1()
{
        while(true)
        {
                flag[1] = true; //P1想使用關鍵區。
                while(flag[0]) //檢查P0是不是也想用?
                {
                        if(turn == 0) //如果P0想用,則查看P0是否具有訪問權限?
                        {
                                flag[1] = false; //如果有,則P1放棄。
                                while(turn == 0); //檢查turn是否屬於P1。
                                flag[1] = true; // P1想使用。
                        }

                }
                  visit(1); //訪問Critical Partition。
                turn = 0; //訪問完成,將權限給P0。
                flag[1] = false; //P1結束使用。
        }
}

void main()
{
        pthread_t t1,t2;
        flag[0] = flag[1] = false;
        turn = 0;
        int err;
        err =  pthread_create(&t1,NULL,(void*)P0,NULL);
        if(err != 0) exit(-1);
        err = pthread_create(&t2,NULL,(void*)P1,NULL);
        if(err != 0 ) exit(-1);
        pthread_join(t1,NULL);
        pthread_join(t2,NULL);
        exit(0);
}

如上所示,如果flag數組和turn都沒有符合使用關鍵區的條件的時候,是不可能進入關鍵區的。

Peterson算法:

Peterson算法也是保證兩個進程(線程)實現互斥的方法,比之前的Dekker算法更加簡單,他同樣提供了兩個變量,保證進程不進入關鍵區,一個是flag[2],一個是turn,兩者的表達意思也類似,flag數組表示能否有權限使用關鍵區,turn是指有訪問權限的進線程ID。(注釋很重要,幫助你理解

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#define true 1
#define false 0
typedef int bool;
bool flag[2];
int turn;
void procedure0()
{
        while(true)
        {
                flag[0] = true;
                turn = 1;
                while(flag[1] && turn == 1)//退出while循環的條件就是,要么另一個線程
//不想要使用關鍵區,要么此線程擁有訪問權限。
                {
                        sleep(1);
                        printf("procedure0 is waiting!\n");
                }
                //critical section
                flag[0] = false;
        }
}
void procedure1()
{
        while(true)
        {
                flag[1] = true;
                turn = 0;
                while(flag[0] && turn == 0)
                {
                        sleep(1);
                        printf("procedure1 is waiting!\n");
                }
                //critical section
                flag[1] = false;
        }
}
void main()
{

        pthread_t t1,t2;
        flag[0] = flag[1] = false;
        int err;
        turn = 0;
        err =  pthread_create(&t1,NULL,(void*)procedure0,NULL);
        if(err != 0) exit(-1);
        err = pthread_create(&t2,NULL,(void*)procedure1,NULL);
        if(err != 0 ) exit(-1);
        pthread_join(t1,NULL);
        pthread_join(t2,NULL);
        exit(0);
}

Bear將turn的賦值放在while循環的后面,然后main函數中賦初值,也是可行的。

如有錯誤,請指正,感激不盡!

參考書籍:

《Modern.Operating.Systems.3rd.Edition》作者:Andrew S.Tanenbaum

參考網站:

https://zh.wikipedia.org/wiki/Peterson

(貌似要翻牆)

http://baike.baidu.com/link?url=h-hOJrsTo24PXgPweosxSpnzeaKhJwhz7N3PbZhG_2_M_8U6RQqEYt9KWGzyclw6lr9Qbi4FkLdyrIKDeBQ6qq

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM