2014-11-02 54 views
8

我想了解Peterson的N進程算法,並且遇到了這個問題。試圖瞭解Peterson的N進程算法

問:假設3個進程具有進程ID 0, 1 and 2。這些進程在單處理器上同時執行,並使用Peterson的N進程算法來控制關鍵部分的執行。每個進程運行以下僞代碼:

lock(pid); 
<critical section>; 
unlock(pid 

其中lock()unlock()函數的定義如

lock(for Process i): 

/* repeat for all partners */ 
for (count = 0; count < (NUMPROCS-1); count++) { 
    flags[i] = count; 
    turn[count] = i; 
    "wait until (for all k != i, flags[k]<count) or (turn[count] != i)" 
} 


Unlock (for Process i): 

/* tell everyone we are finished */ 
flags[i] = -1; 

假設由<flags[0], flags[1], flags[2], turn[0], turn[1]>值所定義的系統在任何特定時間的狀態和的id當前正在執行的進程。進一步假設系統的當前狀態爲<0,0,0,2,-1>而進程0當前正在執行。顯示三個進程從此狀態開始運行到完成的一種特殊方式。在跟蹤三個進程的併發執行時,請在每個步驟顯示系統的狀態。

我的意見上的單處理器並行運行

的進程不能在同一時間在CPU上執行。一次只能在CPU上執行其中的一個。 當一個進程在CPU上執行時,它可能會執行其代碼的任何部分。

// NUMPROCS = 3 

- 對於i = 0

lock(for Process 0): 
for (count = 0; count < 2; count++) { 
    flags[0] = count; 
    turn[count] = 0; 
    "wait until (for all k != 0, flags[k]<count) or (turn[count] != 0)" 
} 


Unlock (for Process 0): 
flags[0] = -1; 

- 對於i = 1

lock(for Process 1): 
for (count = 0; count < 2; count++) { 
    flags[1] = count; 
    turn[count] = 1; 
    "wait until (for all k != 1, flags[k]<count) or (turn[count] != 1)" 
} 


Unlock (for Process 1): 
flags[1] = -1; 

- 對於i = 2

lock(for Process 2): 
for (count = 0; count < 2; count++) { 
    flags[2] = count; 
    turn[count] = 2; 
    "wait until (for all k != 2, flags[k]<count) or (turn[count] != 2)" 
} 


Unlock (for Process 2): 
flags[2] = -1; 

我的問題是,從哪裏開始跟蹤代碼?它被認爲是flags[0]=0, flags[1]=0, flags[2]=0, turn[0]=2, turn[1]=-1,但它將如何幫助我們開始追蹤代碼?

  • 如果我們開始在之前的過程0那麼所有的 轉值將被設置爲比什麼是給 給我們不同的值的循環

  • 如果我們通過執行問題的假設意味着過程0是在它的 關鍵部分,則在接下來的過程中會設置 轉值別的東西的循環。

爲什麼他們給了我們狀態值以及它如何幫助我們找到從哪裏開始跟蹤代碼。

如果我得到一些提示來幫助我開始跟蹤代碼,那將會很棒。

謝謝你,對於長期問題抱歉。

回答

7

既然你沒有問的問題的答案,你問了一個合情合理的問題,我覺得有信心,我可以爲你指明正確的方向,而不直接做作業(或其他)爲您服務。

首先,問題的關鍵部分是在這裏:

在由<flags[0], flags[1], flags[2], turn[0], turn[1]>值和當前正在執行的進程的ID定義的任何給定的時間假設系統的狀態。進一步假設系統的當前狀態是<0,0,0,2,-1>,進程0 當前正在執行

由此我們可以假定系統在其執行過程中正常啓動並達到該狀態。所以我們需要找到一個系統可以處於該狀態並且進程0正在執行的點。下一部分給我們一些迴旋餘地:

顯示從這個狀態開始運行到完成的三個進程的一種特定方式。

因此,可能有多種方法可以通過進程0執行到達這些變量值,但可以找到任何一個變量值並從那裏去完成系統。

此外,我們可以看到所有進程運行一次並退出 - 有一個循環,但我們也可以看到它每次都增加flags的值,所以我們可以很好地猜測,這種情況下爲變量值一次。但我們應該通過它來找出答案。

這些進程正在同時運行,但在單個處理器上運行。所以實際上只有一個正在執行,但一些更高的功率(例如操作系統)正在以我們無法確定的方式在它們之間切換。你說:

當一個進程在CPU上執行時,它可能會執行其代碼的任何部分。

我覺得你只是措辭這個不好,我懷疑你瞭解的現實情況是,每個進程開始之初並運行,直到它的結束,因此「當進程在CPU上執行它開始離開的地方並且可以運行任意數量的指令直到它失去了在CPU上運行的權利(指令的數量取決於控制系統的任何數量)「是更準確的陳述。

所以,最簡單的方法就是要從頭開始,並轉動手柄。這個問題不說,但旗幟,把通常初始化爲-1所以在一開始我們有:

flags = [ -1, -1, -1 ]; turn = [ -1, -1 ] 

由於事情正在同時運行,讓我們姑且認爲每個進程有效地執行,同時每一行。它沒有什麼區別,因爲你希望以後能夠看到自己。

for (count = 0; count < (NUMPROCS-1); count++) { 

OK,算對所有進程= 0,他們都轉到下一行:

flags[i] = count; 

所以現在:

flags = [ 0, 0, 0 ]; turn = [ -1, -1 ] 

到目前爲止,一切都很好 - 下一行:

turn[count] = i; 

好的,這是有問題的 - 每個p rocess試圖設置相同的變量。其中一個將贏,但我們不知道哪一個:

flags = [ 0, 0, 0 ]; turn = [ ?, -1 ] 

除了我們這樣做,因爲它是在問題中。我們可以製作turn[0] = 2。因此,我們在使用變量合適的狀態,我們可以假設進程0是在控制,我們知道這是在這一行:

"wait until (for all k != i, flags[k]<count) or (turn[count] != i)" 

爲了讓您一開始,過程0,計數= 0,I = 0所以

"wait until (for all k in {1,2}, flags[k]<0) or (turn[0] != i)" 

你可以看到or子句是假的,所以進程0將再次去圓循環。那麼過程1. for all k條款對任何人都是不正確的。所以,過程2將等待,因爲turn[0]的價值 - 你也可以看到,這永遠不會改變,所以過程2現在被鎖定等待for all k條款,成爲真正的 - 事實上,這是關鍵,這個系統是如何工作的。如果按照邏輯回答問題,您將看到進程彼此鎖定的情況,以便一次只有一個執行臨界區。只要繼續做上面所做的事情,因爲您只需要找到一條可以同時執行線路的途徑,並且在發生潛在衝突時,您只需從中選擇一個值即可。

你也可以看到,如果過程中有2執行一次它的所有行的人有機會之前,然後處理1,然後再處理0你最終在同一個地方。如果你以各種方式瀏覽整個系統,你會發現類似的模式(請注意,不能保證流程執行關鍵部分的順序,這取決於誰在競爭線上獲勝)。

因此,回到原來的問題,也有隻有少數地方進程0可以與該系統狀態控制。無論是在wait線,或在for線時計數增加1(它循環輪之後)或上線,其中它設置flag[0]。之後,系統狀態不一樣。最好假設過程1中最早的一個未被阻塞(還),並且還可以改變狀態。

最後一個皺紋,爲了保持完整性。還有一個地方可以控制這個過程,系統狀態可以像這樣。它就在turn[count] = i;行之前。在這種情況下,進程2剛剛設置了變量,進程0即將覆蓋它。你可以繼續從這裏開始,但是它將處理循環中的進程1和2。我包括這個預期的評論,我並不建議你以此爲出發點,儘管它是完全有效的。這個問題幾乎肯定會讓你從進程0和進程1開始,在進程中阻塞2個進程,看看發生了什麼。

祝你好運吧。