2014-11-02 17 views
8

Tôi đang cố gắng hiểu Thuật toán N-Process của Peterson và tôi đã xem qua câu hỏi này.Cố gắng hiểu Thuật toán N-Process của Peterson

Câu hỏi: Giả sử 3 quy trình có ID tiến trình 0, 1 and 2. Các quá trình này thực hiện đồng thời trên một bộ xử lý uni và sử dụng thuật toán N-process của Peterson để kiểm soát việc thực thi phần quan trọng. Mỗi quá trình chạy mã giả sau đây:

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

nơi lock()unlock() chức năng được quy định như

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; 

Giả sử trạng thái của hệ thống tại bất kỳ thời gian nhất định được xác định bởi <flags[0], flags[1], flags[2], turn[0], turn[1]> giá trị và id của quá trình thực hiện hiện tại. Giả sử rằng trạng thái hiện tại của hệ thống là <0,0,0,2,-1> với quá trình 0hiện đang thực hiện. Hiển thị một cách cụ thể cho ba quy trình để chạy đến khi hoàn thành bắt đầu từ trạng thái này. Khi bạn theo dõi việc thực hiện đồng thời ba quy trình, hãy hiển thị trạng thái của hệ thống ở từng bước.

quan sát của tôi

Processes chạy đồng thời trên một đơn CPU không thể thực thi trên CPU cùng một lúc. Chỉ một trong số họ có thể thực hiện trên CPU tại một thời điểm. Trong khi quá trình đang thực hiện trên CPU, nó có thể thực hiện bất kỳ phần nào của mã của nó.

// NUMPROCS = 3 

- Đối với 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 với 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 với 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; 

Câu hỏi của tôi là Nơi để bắt đầu truy tìm mã? Nó được đưa ra rằng flags[0]=0, flags[1]=0, flags[2]=0, turn[0]=2, turn[1]=-1 nhưng làm thế nào nó sẽ giúp chúng tôi bắt đầu từ đâu để tìm mã?

  • Nếu chúng ta bắt đầu từ ngay trước khi vòng lặp for của quá trình 0 sau đó tất cả các giá trị lần lượt sẽ được thiết lập để giá trị khác nhau khác so với những gì được đưa ra cho chúng tôi.

  • Nếu chúng tôi giả định bằng cách thực hiện câu hỏi có nghĩa là quy trình 0 nằm trong phần quan trọng của chúng tôi thì vòng lặp cho quy trình tiếp theo sẽ đặt giá trị cho một thứ khác.

Tại sao chúng được cung cấp cho chúng tôi giá trị trạng thái và cách chúng có thể giúp chúng tôi tìm nơi bắt đầu theo dõi mã.

Sẽ thật tuyệt nếu tôi nhận được một số gợi ý để giúp tôi bắt đầu theo dõi mã.

Cảm ơn và xin lỗi vì câu hỏi dài.

Trả lời

7

Vì bạn không yêu cầu câu trả lời cho câu hỏi và bạn đã hỏi một câu hỏi hợp lý và hợp lý, tôi cảm thấy tự tin mình có thể chỉ cho bạn đúng hướng mà không làm bài tập ở nhà của bạn (hoặc bất kỳ điều gì) cho bạn.

Thứ nhất, phần quan trọng của vấn đề là ở đây:

Giả sử trạng thái của hệ thống tại bất kỳ thời gian nhất định được xác định bởi <flags[0], flags[1], flags[2], turn[0], turn[1]> giá trị và id của quá trình hiện thực. Giả sử rằng trạng thái hiện tại của hệ thống là <0,0,0,2,-1> với quá trình 0 hiện đang thực hiện.

Từ đây chúng ta có thể giả định rằng hệ thống đã được khởi động bình thường và đến trạng thái đó trong khi thực thi. Vì vậy, chúng ta cần phải tìm một điểm mà hệ thống có thể ở trạng thái đó và quá trình 0 đang thực hiện. Phần tiếp theo cung cấp cho chúng tôi một số phòng lung linh:

Hiển thị một cách đặc biệt cho ba quy trình chạy đến khi hoàn tất bắt đầu từ trạng thái này.

Vì vậy, có thể có nhiều cách để có được các giá trị biến đó với quá trình thực hiện 0 nhưng không thể tìm thấy bất kỳ giá trị nào và đi từ đó để hoàn thành hệ thống. Hơn nữa, chúng ta có thể thấy rằng tất cả các quá trình chạy một lần và thoát - có một vòng lặp nhưng chúng ta cũng có thể thấy rằng nó tăng giá trị của flags trên mỗi lượt để chúng ta có thể đoán tốt rằng chúng tôi chỉ nhấn kịch bản này cho các giá trị biến một lần. Nhưng chúng ta nên làm việc thông qua nó để tìm hiểu.

Các quy trình đang chạy đồng thời, nhưng trên một bộ xử lý duy nhất. Vì vậy, trong thực tế chỉ có một người từng thực hiện nhưng một số quyền lực cao hơn (một hệ điều hành chẳng hạn) đang chuyển đổi giữa chúng theo cách chúng ta không thể xác định. Bạn nói:

Trong khi quá trình đang thực thi trên CPU, nó có thể thực thi bất kỳ phần nào của mã.

Tôi nghĩ bạn đã hiểu rõ điều này, tôi nghi ngờ bạn hiểu thực tế là mỗi quá trình bắt đầu từ đầu và chạy cho đến khi kết thúc, do đó "Trong khi quá trình đang thực thi trên CPU, nó bắt đầu từ khi nó dừng lại và có thể chạy bất kỳ số lượng hướng dẫn nào cho đến khi nó mất quyền chạy trên CPU (số lượng hướng dẫn là tùy thuộc vào bất cứ điều gì đang kiểm soát hệ thống) "là một tuyên bố chính xác hơn.

Vì vậy, cách dễ nhất chỉ là bắt đầu từ đầu và xoay tay cầm. Câu hỏi đặt ra không nói điều này nhưng cờ và biến thường được khởi tạo -1 nên ngay từ đầu chúng ta có:

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

Kể từ khi mọi thứ đang chạy đồng thời chúng ta hãy chỉ cho rằng mỗi quá trình có hiệu quả thực thi mỗi dòng cùng một lúc. Nó không tạo ra bất kỳ sự khác biệt nào, vì bạn hy vọng sẽ có thể tự mình nhìn thấy sau này.

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

OK, count = 0 cho tất cả các quá trình và tất cả họ đều đi vào dòng tiếp theo:

flags[i] = count; 

Vì vậy, bây giờ:

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

Cho đến nay, như vậy tốt - dòng tiếp theo :

turn[count] = i; 

OK, đó là vấn đề - mỗi p rocess cố gắng đặt cùng một biến. Một trong số họ sẽ giành chiến thắng nhưng chúng tôi không biết cái nào:

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

Trừ khi chúng tôi làm như trong câu hỏi. Chúng tôi có thể thực hiện turn[0] = 2. Vì vậy, chúng tôi đang ở trong một trạng thái phù hợp với các biến, chúng ta có thể giả định quá trình 0 là trong kiểm soát và chúng ta đều biết đó là trên dòng này:

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

Để giúp bạn bắt đầu, cho quá trình 0, count = 0 và i = 0 so

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

Bạn có thể thấy mệnh đề or là sai, do đó quy trình 0 sẽ lặp lại vòng lặp. Vì vậy, sẽ xử lý 1. Các khoản for all k là không đúng cho bất cứ ai. Vì vậy, quá trình 2 sẽ chờ vì giá trị của turn[0] - bạn cũng có thể thấy rằng điều này sẽ không bao giờ thay đổi, do đó, quá trình 2 hiện đang bị khóa chờ mệnh đề for all k trở thành sự thật - thực tế đó là chìa khóa cho cách hoạt động của hệ thống này. Nếu bạn làm theo logic thông qua để trả lời câu hỏi, bạn sẽ thấy các quy trình khóa lẫn nhau ra sao để chỉ có một thực thi từng phần quan trọng tại một thời điểm. Chỉ cần tiếp tục làm những gì tôi đã làm ở trên, vì bạn chỉ cần tìm một lộ trình bạn có thể thực hiện các dòng cùng một lúc và khi có một xung đột tiềm năng chỉ cần chọn một giá trị và đi từ đó. Bạn cũng có thể thấy rằng nếu quá trình 2 đã thực hiện tất cả các dòng của nó cùng một lúc trước khi những người khác có cơ hội, và sau đó xử lý 1 và sau đó xử lý 0 bạn sẽ kết thúc ở cùng một vị trí. Nếu bạn làm việc thông qua toàn bộ hệ thống theo nhiều cách khác nhau, bạn sẽ tìm thấy mẫu tương tự (lưu ý rằng không có sự đảm bảo nào về thứ tự các quá trình sẽ thực hiện các phần quan trọng của nó, nó phụ thuộc vào ai 'thắng' trên các dòng bị tranh cãi).

Quay lại câu hỏi ban đầu, chỉ có một vài nơi mà quy trình 0 có thể được kiểm soát với trạng thái hệ thống đó. Hoặc trên đường dây wait hoặc trên đường dây for khi số được tăng lên 1 (sau khi vòng lặp) hoặc trên đường nơi đặt flag[0]. Sau đó trạng thái hệ thống không giống nhau. Tốt nhất để giả định sớm nhất là quá trình 1 không bị chặn (chưa) và cũng có thể thay đổi trạng thái.

Một nếp nhăn cuối cùng, để hoàn thành. Có một nơi khác mà quy trình đó có thể được kiểm soát và trạng thái hệ thống có thể giống như vậy. Và ngay trước dòng turn[count] = i;. Trong quá trình kịch bản 2 này vừa thiết lập biến và tiến trình 0 sắp sửa ghi đè nó. Bạn có thể tiếp tục từ đây nhưng nó sẽ là các quy trình 1 và 2 đi vòng quanh. Tôi bao gồm này dự đoán một bình luận về nó, tôi không thực sự đề nghị bạn sử dụng này như là điểm khởi đầu mặc dù nó hoàn toàn hợp lệ. Câu hỏi gần như chắc chắn hy vọng bạn bắt đầu từ các quá trình 0 và 1 đi vòng vòng, với 2 bị chặn trong chờ đợi bận rộn để xem những gì xảy ra từ đó.

Chúc bạn may mắn với nó.

Các vấn đề liên quan