Thuật toán trong mạng không đồng bộ

Một phần của tài liệu Nghiên cứu các thuật toán giám sát và xử lý cạnh tranh giữa các thành phần phần mềm trên môi trường phân tán (Trang 44 - 47)

Trong mô hình này, các thành phần khác nhau thực hiện các bước theo thứ tự tuỳ ý. Không giống như mô hình tính toán trong các thuật toán đồng bộ, mô hình tính toán trong các thuật toán không đồng bộ không sử dụng các hàm sinh thông điệp, mọi giao tiếp đều thông qua bộ nhớ chia sẻ[4].

Mô hình bộ nhớ chia sẻ

Mô hình này bao gồm một tập các tiến trình và các ô nhớ chia sẻ, được thể hiện tại hình 3.2

Trước đây, tiến trình có thể coi là máy trạng thái. Mỗi tiến trình có một tập các trạng thái states và tập con start. Ngày nay, các tiến trình còn được gán nhãn actions

để mô tả hoạt động bên trong. Các action được phân loại thành input, output

internal. Internal cũng được phân ra thành hai loại: một loại để chỉ bộ nhớ chia sẻ, một loại để chỉ sự tính toán cục bộ.

Có một quan hệ chuyển tiếp trans, là một tập các bộ ba (s, π, s’), trong đó π là nhãn của một action input, output hoặc sự tính toán cục bộ. Bộ ba (s, π, s’) có nghĩa là từ trạng thái s có thể chuyển sang trạng thái s’ khi thực hiện action π. Trans không phải là hàm mà là quan hệ, do đó nó có thể có giá trị không xác định.

Hình 3.2: hệ thống bộ nhớ chia sẻ. Vòng elip thể hiện tiến trình, ô chữ nhật là ô nhớ chia sẻ, mũi tên là giao tiếp với bên ngoài (input và output)

Chúng ta thừa nhận rằng input action luôn luôn là enabled, do đó với mỗi trạng thái

s và một input action π, luôn luôn tồn tại một trạng thái s’ sao cho (s, π, s)  trans. Các action là output và tính toán cục bộ chỉ có thể là enabled trong tập con của tập trạng thái states. Với tính chất như vậy input là do người dùng bên ngoài điều khiển còn output và tính toán cục bộ là do hệ thống điều khiển.

Khi truy cập bộ nhớ chia sẻ thì quan hệ trans có dạng ((s, m), π, (s’, m’)), trong đó s, s’ là trạng thái tiến trình, m, m’ là trạng thái bộ nhớ chia sẻ. Một điểm đặc biệt chúng ta cần chú ý là trạng thái enabling của hoạt động truy cập bộ nhớ chia sẻ chỉ là trạng thái tiến trình cục bộ chứ không phải là bộ nhớ chia sẻ; tuy nhiên, trạng thái respond, sự thay đổi trạng thái của tiến trình và của bộ nhớ chia sẻ lại có thể cũng là trạng thái của bộ nhớ chia sẻ. Tính chất này có thể được phát biểu như sau: nếu action π

enabled trong (s,m) thì đối với tất cả trạng thái bộ nhớ m’, πeabled trong (s,m’). Trong một số trường hợp đặc biệt, các truy cập có thể có các ràng buộc khác nữa.

Một hạn chế chung nhất là chỉ cho phép truy cập tại một địa chỉ và thực hiện được một bước. Một hạn chế khác là các truy cập chỉ là read hoặc write. Hoạt động read là copy giá trị của địa chỉ bộ nhớ chia sẻ tới một biến cục bộ còn hoạt động write là viết giá trị lên một địa chỉ bộ nhớ chia sẻ, overwriting cũng như vậy.

Mô hình thực thi rất khác trước. Hiện nay các tiến trình cho phép thực hiện nhiều bước trong cùng một thời điểm theo một thứ tự tuỳ ý ( không phải thực hiện các bước trong các vòng đồng bộ). Sự tuỳ ý ở đây thực chất là sự không đồng bộ. Nói một cách chính thức, sự thực hiện là một chuỗi liên tiếp s0, π, s1,…, gồm có các trạng thái hệ thống (trạng thái của các tiến trình và các bộ nhớ chia sẻ) và các hoạt động liên tiếp (mỗi hoạt động là của một tiến trình riêng biệt), trong đó các bộ ba (state, action, state) thoả mãn quan hệ chuyển tiếp. Một thực thi có thể là một chuỗi hữu hạn hoặc vô hạn.

Một điểm quan trọng trong sự tuỳ ý này là không cho phép một tiến trình đang thực hiện bị dừng lại giữa chừng. Tình huống này xảy ra khi một tiến trình đang ở trạng thái có một hoạt động điều khiển cục bộ nào đó (không phải là hoạt động input) là enabled (Nhắc lại rằng các hoạt động input đều là enabled). Nếu tiến trình chỉ có hữu hạn bước thực hiện thì bước thực hiện cuối cùng sẽ đưa tiến trình đến trạng thái mà không có hoạt động điều khiển cục bộ nào là enabled. Nhưng đối với các tiến trình có vô hạn bước thực hiện thì đến một thời điểm nào đó, các bước này sẽ trở thành các bước input. Như vậy các tiến trình tự quay vòng. Tuy nhiên, nếu như xuất hiện vô hạn các hoạt động input mà không có hoạt động điều khiển cục bộ nào thì trên thực tế sẽ không có hoạt động điều khiển cục bộ nào là enabled. Nó cũng giống như là tiến trình “có khả năng” để thực hiện các bước nhưng nó không muốn thực hiện.Các khả năng có thể sẽ được mô tả trong định nghĩa sau:

Với mỗi tiến trình i:

1. Toàn bộ quá trình thực thi là hữu hạn, và tại trạng thái kết thúc không có một hoạt động điều khiển cục bộ nào của tiến trình i là enable hoặc

2. Quá trình thực thi là vô hạn và trong chuỗi thi hành đó hoặc là có vô số vị trí mà trong đó tiến trình i đang thực hiện một hoạt động cục bộ hoặc có vô kể trạng thái mà trong đó không có một hoạt động nào ở trạng thái enabled.

Mô hình tính toán của các thuật toán không đồng bộ

Cũng giống như trong mạng đồng bộ, chúng ta có một đồ thị (vô hướng hoặc có hướng) G với các nút là các tiến trình và được nối với nhau bởi các cạnh.

Mỗi tiến trình là một IOA(Input/Output Atomaton-bộ đầu vào/đầu ra tự động), kết nối với bên ngoài bởi các input và output. Với mỗi tiến trình i, output có dạng sendi,j(m), trong đó j là một láng giềng đi ra từ i, m là thông điệp (một phần tử của tập thông điệp M); còn input có dạng receivej,i(m), trong đó j là một láng giềng đi đến i. Ngoại trừ việc hạn chế về mặt giao diện, tiến trình có thể coi là một IOA tuỳ ý. (Đôi khi chúng ta cũng giới hạn số lượng lớp hay số lượng trạng thái… để đạt được các kết quả phức tạp)

Để mô hình hóa việc kết nối, chúng ta sẽ đặc tả hành vi cho trình tự của các hoạt động send(i,j) và receive(i,j) đối với mỗi cạnh (i,j). Có hai cách thực hiện: liệt kê các thuộc tính hay các tiên đề, hoặc đưa ra một IOA có các hành vi đúng theo trình tự yêu cầu. Lợi thế của việc dùng IOA chính là toàn bộ hệ thống sẽ được mô tả như là một khối và chúng ta sẽ có thông tin của về các trạng thái của toàn bộ hệ thống để dùng trong việc chứng minh tính bất biến và chứng minh bằng mô phỏng. Tuy nhiên, đôi khi chúng ta cũng phải lập trình một cách bất bình thường để có thể đặt tả các hành vi được yêu cầu như là một IOA, đặt biệt là khi chúng ta muốn mô tả các ràng buộc liveness. Chúng ta sẽ định nghĩa các khái niệm quan trọng về safety và liveness:

Đặt S và L là các thuộc tính của các chuỗi hoạt động. S là một thuộc tính safety nếu nó thoả mãn các điều kiện sau:

S là khác rỗng (tức là có vài trình tự thoả mãn S)

S là prefix-closed (tức là nếu một trình từ thoả mãn S thì tất cả các trình tự trước nó đều thoả mãn S)

S là limit-closed (tức là nếu tất cả các trình từ hữu hạn trước của một trình từ vô hạn thoả mãn S thì trình tự vô hạn đó cũng thoả mãn S)

L là thuộc tính liveness nếu với tất cả các trình tự hữu hạn, các mở rộng của nó đều thoả mãn L. Ta có thể hiểu các thuộc tính safety thể hiện là “không có lỗi xảy ra” - nếu không có lõi xảy ra trong trình tự hữu hạn thì không có lỗi xảy ra trong các trình tự trước đó, hơn nữa, nếu có lỗi xảy ra thì nó chỉ xảy tại thời điểm ngay lúc đó. Trong khi đó thuộc tính liveness lại ngụ ý rằng “sự tốt đẹp đang diễn ra”.

Chúng ta hãy trở lại với mô hình truyền thông điệp không đồng bộ. Kênh kết nối chung nhất trong các tài liệu nghiên cứu chính là kênh FIFO. Đây là một IOA với các giao diện tương ứng, trạng thái của nó chính là hàng đợi các thông điệp. Hoạt động send(i,j) sẽ đặt biến của nó vào cuối hàng đợi. Hoạt động receivei,j(m) là enabled nếu

m được đẩy lên đầu hàng đợi. Tác động của nó là lấy thông điệp ra khỏi hàng đợi. Và tất nhiên là nó phân phối thông điệp đến các tiến trình nhận. Nhưng đấy là phần việc của tiến trình chứ không phải là của kênh.

Các vấn đề cần giải quyết trong mô hình này:

Mutual exclution: vấn đề này liên quan đến bộ nhớ chia sẻ, giải quyết vấn đề tương tranh xảy ra khi cùng một lúc có nhiều tiến trình cùng truy cập đến một địa chỉ. Đây là vấn đề căn bản nhất trong lĩnh vực này. Sự không rõ ràng ở đây chính là không biết tiến trình nào yêu cầu truy cập tài nguyên và khi nào yêu cầu. Các thuật toán giải quyết vấn đề này: Mutual exclution của Dijkstra, Two-Process của Peterson, Mutual exclution của Burn, Bakery của Lamport (adsbygoogle = window.adsbygoogle || []).push({});

Tính toán trong đồ thị tĩnh: đây là mô hình đơn giản nhất trong mô hình không đồng bộ, có các input tại thời điểm bắt đầu và chỉ sinh ra một output. Bài toán ví dụ cho mô hình này là tìm leader trong mạng vòng và tìm cây khung tối thiểu.

Đồng bộ mạng: Thuật toán thứ nhất là của Lamport, đưa ra một phương thức gán giá trị thời gian logic cho các sự kiện trong mạng phân tán, cho phép mô phỏng mạng không đồng bộ thành một mạng có các nút truy cập theo đồng hồ thời gian thực đồng bộ. Thuật toán thứ hai là của Awerbuch cho phép mô phỏng mạng không đồng bộ thành mạng đồng bộ lock-step. Thuật toán thứ ba là mô phỏng mạng không đồng bộ thành máy trạng thái tập trung(không phân tán). Thuật toán thứ tư là mô phỏng mạng không đồng bộ thành bộ nhớ chia sẻ không đồng bộ.

Xác định các thuộc tính ổn định: giả sử ta có một thuật toán đang chạy, chúng ta lại thiết kế thêm một thuật toán khác dùng để “giám sát” thuật toán thứ nhất (đang chạy). Giám sát ở đây có nghĩa là xác định xem khi nào thì thuật toán kết thúc hay bị tắc nghẽn

Các thuật toán cho vấn đề truyền thông: các giao thức tầng Datalink, giải quyết vấn đề thi hành các kết nối truyền thông tin cậy trên các kênh không tin cậy; các khối xây dựng mạng có sẵn với chức năng đặc biệt như: truyền đại chúng-truyền hội tụ, khởi động lại, điểm-tới …

Chúng ta sẽ cùng xem xét một số thuật toán giải quyết vấn đề mutual exclution.

Một phần của tài liệu Nghiên cứu các thuật toán giám sát và xử lý cạnh tranh giữa các thành phần phần mềm trên môi trường phân tán (Trang 44 - 47)