1. Trang chủ
  2. » Giáo án - Bài giảng

TÌM HIỂU PHƯƠNG PHÁP ĐỒNG BỘ HÓA TIẾN TRÌNH SEMAPHORES – VIẾT ỨNG DỤNG MINH HỌA BÀI TOÁN TIẾN TRÌNH ĐỌC - GHI (READERS – WRITERS)

34 22 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Tìm Hiểu Phương Pháp Đồng Bộ Hóa Tiến Trình Semaphores – Viết Ứng Dụng Minh Họa Bài Toán Tiến Trình Đọc - Ghi (Readers – Writers)
Tác giả Nhóm 11
Người hướng dẫn Thầy Lê Anh Tuấn
Trường học Trường Đại học Công nghiệp Thực phẩm TP. HCM
Chuyên ngành Hệ Điều Hành
Thể loại Tiểu luận
Năm xuất bản 2022
Thành phố TP. Hồ Chí Minh
Định dạng
Số trang 34
Dung lượng 1,04 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Cấu trúc

  • CHƯƠNG 1: CÁC KHÁI NIỆM LIÊN QUAN (6)
    • I. K HÁI NIỆM ĐỒNG BỘ HÓA GIỮA CÁC TIẾN TRÌNH (6)
    • II. V ẤN ĐỀ ĐOẠN GĂNG (6)
      • 1. Tài nguyên găng (Critical Resource) (6)
      • 2. Đoạn găng (Critical Section) (7)
      • 3. Điều kiện thỏa mãn đoạn găng (7)
  • CHƯƠNG 2: CÁC GIẢI PHÁP ĐỒNG BỘ (8)
    • I. G IẢI P HÁP S EMAPHORE (8)
      • 1. Định nghĩa (8)
      • 2. Hoạt động (9)
      • 3. Phân loại Semaphora (11)
      • 4. Tổ chức truy xuất độc quyền (14)
      • 5. Tổ chức đồng bộ hóa phối hợp hoạt động (14)
      • 6. Nhận xét (15)
      • 7. Một số chú ý khi sử dụng semaphore (16)
    • II. G IẢI PHÁP “BUSY - WAITING” (16)
      • 1. Giải pháp phần cứng (16)
      • 2. Giả pháp phần mềm (17)
    • III. G IẢI PHÁP “SLEEP AND WAKE UP” (19)
      • 1. Giải pháp Monitor (21)
      • 2. Giải pháp trao đổi thông điệp (message passing) (24)
  • CHƯƠNG 3: BÀI TOÁN READER/WRITER (26)
    • I. G IỚI THIỆU BÀI TOÁN (26)
    • II. G IẢI QUYẾT BÀI TOÁN (29)
      • 1. Cấu trúc của Reader (29)
      • 2. Cấu trúc của Writer (29)
      • 3. Chương trình bài toán Readers/Writers (30)
      • 4. Kết quả chương trình (33)
  • TÀI LIỆU THAM KHẢO (34)

Nội dung

Tài nguyên găng Critical Resource - Các tiến trình hoạt động đồng thời thường cạnh tranh nhau trong việc sử dụng tài nguyên dùng chung cùng ghi vào không ghi nhớ chung hay cùng ghi dữ li

CÁC KHÁI NIỆM LIÊN QUAN

K HÁI NIỆM ĐỒNG BỘ HÓA GIỮA CÁC TIẾN TRÌNH

Đồng bộ tiến trình là gì? Đồng bộ các tiến trình là bảo đảm các tiến trình xử lý song song không tác động sai lệch đến nhau Đồng tiến trình có lẽ hoặc trực tiếp chia sẻ một không gian địa chỉ (có nghĩ là, cả mã nguồn và dữ liệu), hoặc được cho phép để chia sẻ dữ liệu chỉ thông qua các file Một trường hợp chính tắc đạt được khi sử dụng các tiến trình đơn giản hoặc các tuyển Cùng nhập vào chia sẻ dữ liệu có thể kết quả sẽ dẫn đến xung khắc dữ liệu

Tại sao phải dồng bộ giữa các tiến trình?

- Yêu cầu độc quyền truy xuất (mutual exclusion): tại một thời điểm, chỉ có một tiến trình được quyền truy xuất một tài nguyên không thể chia sẻ.

- Yêu cầu phối hợp (synchroniztion): các tiến trình cần hợp tác với nhau để hoàn thành công việc Ví dụ chương trình in sẽ xuất kí tự vào buffer, chương trình điều khiển máy in (printer driver) sẽ lấy kí tự trong buffer ra để in hai tiến trình này phải phối hợp với nhau để làm sao chương trình in không được xuất kí tự vào buffer khi buffer đầy mà phải chời printer driver lấy bớt dữ liệu trong buffet ra.

V ẤN ĐỀ ĐOẠN GĂNG

1 Tài nguyên găng (Critical Resource)

- Các tiến trình hoạt động đồng thời thường cạnh tranh nhau trong việc sử dụng tài nguyên dùng chung (cùng ghi vào không ghi nhớ chung hay cùng ghi dữ liệu vào một file chia sẻ).

Những tài nguyên có nguy cơ bị hư hỏng hoặc sai lệch khi được hệ điều hành chia sẻ đồng thời cho nhiều tiến trình được gọi là tài nguyên găng Việc các tiến trình đồng thời truy cập tài nguyên có thể làm mất tính nhất quán dữ liệu và khiến trạng thái của tài nguyên bị nhiễu loạn Để ngăn ngừa hiện tượng này, hệ điều hành và các lớp quản trị tài nguyên phải triển khai cơ chế đồng bộ hóa, khóa tài nguyên và quản lý quyền truy cập một cách có kế hoạch, giảm thiểu rủi ro tranh chấp và đảm bảo hệ thống hoạt động ổn định.

Trong hệ thống CNTT, tài nguyên được phân loại thành tài nguyên phần cứng, tài nguyên phần mềm và các loại tài nguyên có thể phân chia được hoặc không phân chia được Tài nguyên phần cứng gồm CPU, RAM và thiết bị lưu trữ; tài nguyên phần mềm là các dịch vụ, ứng dụng và giấy phép sử dụng Đa số tài nguyên có thể phân chia được, ví dụ như các biến chung và file chia sẻ, cho phép cấp phát và truy cập đồng thời của nhiều tiến trình hoặc người dùng Việc nhận diện đúng loại tài nguyên và mức độ phân chia phù hợp giúp tối ưu quản lý, nâng cao hiệu suất và đảm bảo an toàn dữ liệu cho hệ thống.

Xem xét một hệ thống bao gồm n tiến trình Mỗi tiến trình có một đoạn mã lệnh, được gọi là đoạn găng, trong đó tiến trình có lẽ đang thay đổi biến chung, cập nhập một bảng, viết một tệp, những gì tương tự thế Đặc trưng quan trọng của một hệ thống là, khi một tiến trình đang thực thi trong đoạn găng của nó Vì vậy, việc thực thi của đoạn găng bởi tiến trình tranh chấp đúng lúc Vấn đề đoạn găng thiết kế một giao thức mà tiến trình có thể sử dụng để hợp tác Mỗi tiến trình phải chấp nhận yêu cầu để nhập vào đoạn găng của nó Phần mã lệnh thực hiện yêu cầu này được gọi là đoạn tiếp nhận

(entry section) Đoạn găng có lẽ được tiếp tục bởi một thoát đoạn Đoạn mã lệnh còn phải là phần dư

3 Điều kiện thỏa mãn đoạn găng

Yêu cẩu cho vấn đề đoạn găng cũng là yêu cầu của đồng bộ hóa tiến trình Theo đó cần thỏa mãn 3 điều kiện sau:

Loại bỏ tranh chấp (Mutual Exclusion) là cơ chế đảm bảo khi một tiến trình đang thực thi trong đoạn găng của nó thì không có tiến trình nào khác được phép thực thi cùng lúc trong cùng đoạn găng đó, nhằm ngăn xung đột truy cập tài nguyên và duy trì tính nhất quán của dữ liệu giữa các tiến trình Để thực thi mutual exclusion, hệ thống sử dụng các biện pháp như khóa (lock), semaphore hoặc biến trạng thái để cấp quyền truy cập độc quyền cho tiến trình hiện tại và từ chối các tiến trình khác cho đến khi tiến trình đó hoàn thành phần quan trọng.

Trong cơ chế quản lý tiến trình và đồng bộ hóa, một tiến trình tạm dừng ở bên ngoài miền găng không ngăn cản các tiến trình khác vào miền găng Khi không còn tiến trình nào đang ở trong đoạn găng và có tiến trình khác muốn vào, những tiến trình chưa thực thi phần còn lại sẽ được xem là ứng viên cho quyền truy cập Lựa chọn ứng viên vào miền găng tại thời điểm này là bắt buộc và không thể bị hoãn.

- Giới hạn đợi (Bounded wait): Không có tiến trình nào phải chờ đợi vô hạn để được vào miền găng Giới hạn số lần các tiến trình được phép vào đoạn găng của chúng ta khi một tiến trình thực hiện yêu cầu đi vào đoạn găng và trước khi yêu cầu đó được giảm.

CÁC GIẢI PHÁP ĐỒNG BỘ

G IẢI P HÁP S EMAPHORE

- Là một trong những đóng góp quan trọng của nhà toán học người Hà

Lan Edsger Wybe Dijkstra, Semaphore là một công cụ đồng bộ cung cấp bởi OS mà không đỏi hỏi Busy Waiting.

- Semaphore về cơ bản là một biến không âm tính đến toán tử khởi tạo, nó chỉ có thể truy cập thông qua hai toán tử nguyên tố là wait (Down hay

P) và signal (Up hay V) b) Đặc tính

- Hai thao tác được định nghĩa trên semaphore:

 Down(s): giảm s đi 1 đơn vị Nếu giá trị s âm process phỉa chờ,ngược lại thì tiếp tục xử lý.

Up(s) là thao tác tăng biến s lên một đơn vị Khi có một hoặc nhiều tiến trình đang chờ trên semaphore s bị khóa bởi thao tác Down, hệ thống sẽ chọn một trong các tiến trình này để kết thúc thao tác Down và tiếp tục xử lý.

 Hai thao tác này có tính nguyên tố, nghĩa là không bị ngắt giữa chừng

Hình 1 Hoạt động của giải pháp Semaphore

- Khi count đang lớn hơn 0, tức là semaphore đang ở trạng thái AVAILABLE, nếu một thread gọi hàm down, thì biến count bị giảm đi

1 đơn vị (nếu hiệu bằng 0 thì semaphore chuyển sang trạng thái UNAVAILABLE) Sau đó, CPU bắt đầu thực thi critical section của thread (nói theo ngôn ngữ của CPU), hay thread bắt đầu sử dụng critical resource (nói theo ngôn ngữ của Linux kernel).

- Khi count đang bằng 0, tức là semaphore đang ở trạng thái UNAVAILABLE, nếu một thread gọi hàm down, thì CPU tạm dừng thực thi thread này rồi chuyển sang thực thi thread khác (nói theo ngôn ngữ của CPU) Hay nói theo ngôn ngữ của Linux kernel, thread đó được thêm vào hàng đợi wait_list và đi ngủ, sau đó Linux kernel sẽ lập lịch cho thread khác Do đó, ta nói rằng, semaphore áp dụng cơ chế sleep-waiting.

- Khi wait_list vẫn còn ít nhất một thread đang phải đợi, nếu một thread

A gọi hàm up, thì CPU sẽ chuyển sang thực thi thread B nằm ở vị trí đầu tiên trong hàng đợi wait_list (nói theo ngôn ngữ của CPU) Hay nói theo ngôn ngữ của Linux kernel, Linux kernel đánh thức thread B dậy, sau đó thread B bắt đầu sử dụng critical resource.

Trong cơ chế semaphore, khi wait_list không còn thread nào chờ đợi, một lần gọi hàm up từ một thread sẽ làm tăng count lên 1, đồng nghĩa semaphore chuyển sang trạng thái AVAILABLE để các thread khác có thể tiếp tục hoặc giành quyền truy cập tài nguyên.

Semaphore có 2 thành phần chính: biến count và hàng đợi wait_list Căn cứ vào biến count mà semaphore được chia làm 2 loại: a) Counting Semaphore (Đếm Semaphore)

Giá trị cực đại của biến count được đặt ở mức lớn hơn 1 và đại diện cho số lượng tiến trình tối đa có thể đồng thời sử dụng critical-section Việc giới hạn giá trị này giúp kiểm soát mức độ truy cập đồng thời, đảm bảo an toàn đồng bộ và hiệu quả quản lý truy cập vào critical-section tại mỗi thời điểm.

Trong triển khai này, mỗi khi một tiến trình phải đợi, nó được đưa vào hàng đợi các tiến trình liên kết với semaphore đó Việc đưa tiến trình vào hàng đợi diễn ra thông qua khối lệnh gọi hệ thống trên tiến trình đó, nhằm mục đích quản lý đồng bộ hóa và điều phối các tiến trình đang chờ theo cơ chế semaphore một cách hiệu quả.

Khi một tiến trình hoàn tất, nó gọi hàm tín hiệu và một tiến trình đang ở hàng đợi được tiếp tục thực thi, thông qua một cuộc gọi hệ thống được gọi là awup Bài viết tiếp tục với khái niệm Binary Semaphore (Semaphore nhị phân), một cơ chế đồng bộ hóa cho phép quản lý quyền truy cập vào tài nguyên chung bằng một biến semaphore có giá trị 0 hoặc 1, giúp các tiến trình phối hợp và tránh các trạng thái race khi làm việc song song.

- Nếu biến count chỉ có hai giá trị 0 và 1, thì semaphore được gọi là binary semaphore Binary semaphore có một số nét tương đồng với mutex lock.

- Mô tả ở trên dành cho semaphore nhị phân chỉ có thể nhận hai giá trị 0 và

1 và đảm bảo loại trừ lẫn nhau Có một loại semaphore khác được gọi là semaphore đếm có thể nhận các giá trị lớn hơn một.

- Bây giờ, giả sử có một tài nguyên có số lượng cá thể là 4 Bây giờ chúng ta khởi tạo S = 4 và phần còn lại giống như đối với semaphore nhị phân.

Trong cơ chế đồng bộ hóa bằng semaphore, khi một tiến trình muốn một tài nguyên, nó thực hiện P (wait) để chặn cho đến khi tài nguyên sẵn sàng; một khi được cấp phát, nó thực hiện V (signal) để báo hiệu tài nguyên đã được giải phóng cho các tiến trình khác Giá trị của S đại diện cho số lượng tài nguyên còn lại và nếu S bằng 0 thì các tiến trình khác phải đợi cho đến khi S trở thành dương Ví dụ, nếu một tài nguyên duy nhất có S=1 và một tiến trình chiếm nó bằng P, S sẽ giảm xuống 0 và các tiến trình khác sẽ bị chặn cho đến khi tiến trình hiện tại gọi V và tăng S lên lại.

Giả sử có 4 tiến trình P1, P2, P3, P4 và chúng đều gọi thao tác chờ trên S

Semaphores được khởi tạo với giá trị ban đầu là 4, cho phép tối đa bốn tiến trình cùng lúc nhận tài nguyên Khi một tiến trình khác, ví dụ P5, muốn tài nguyên, nó phải đợi cho đến khi một trong bốn tiến trình gọi hàm tín hiệu và giá trị của semaphore được tăng lên, trở thành dương để cấp phát lại tài nguyên Đây là minh họa cho cơ chế đồng bộ hóa dựa trên semaphore c) So sánh hai loại đồng bộ hóa sẽ được trình bày ở phần tiếp theo, nhằm làm rõ ưu nhược điểm và ngữ cảnh sử dụng của từng loại trong quản lý tài nguyên giữa các tiến trình.

4 Tổ chức truy xuất độc quyền

- Semaphore bảo đảm nhiều tiến trình cùng truy xuất mà không có sự mâu thuẫn.

- Giả sử n tiến trình cùng sử dụng một semaphore s, được khởi tạo bằng 1.

- Để thực hiện đồng bộ hóa, tất cả các tiến trình cần phỉa áp dụng cùng cấu trúc chương trình:

5 Tổ chức đồng bộ hóa phối hợp hoạt động:

- Sử dụng semaphore có thể đồng bộ hóa hoạt động của hai tiến trình trong tình huống một tiến trình phải đợi một tiến trình khác hoàn tất thao tác nào đó mới có thể bắt đầu hay tiếp tục xử lý.

- Hai tiến trình chia sẻ một semaphore s, khởi tạo bằng 0 Cấu trúc:

 Nó cho phép nhiều hơn một luồng truy cập vào critical - section.

 Có thể thiết lập không cho phép nhiều process vào critical-section.

 Vì có quá trình “busy waiting” trong semaphore, thời gian và tài nguyên sẽ không bị lãng phí.

 Cho phép quản lý tài nguyên linh hoạt.

 Một trong những hạn chế lớn nhất của semaphore là đảo ngược ưu tiên.

 Hệ điều hành phải theo dõi tất cả các cuộc gọi để chờ và báo hiệu cho semaphore.

 Việc sử dụng chúng không bao giờ được thực thi mà chỉ là theo quy ước.

 Để tránh deadlock trong semaphore, các hoạt động Wait và Signal yêu cầu phải được thực hiện theo đúng thứ tự.

 Lập trình Semaphore là một công việc phức tạp, vì vậy có khả năng không đạt được loại trừ lẫn nhau.

 Nó cũng không phải là một phương pháp thực tế để sử dụng trên quy mô lớn vì việc sử dụng chúng dẫn đến mất tính mô đun.

 Semaphore dễ bị lỗi lập trình viên hơn.

 Nó có thể gây ra bế tắc hoặc vi phạm loại trừ lẫn nhau do lỗi của người lập trình.

7 Một số chú ý khi sử dụng semaphore

Khi triển khai giải pháp này, ta cần chú ý đến một số điểm sau:

- Do semaphore áp dụng cơ chế chờ đợi sleep-waiting, nên ta chỉ sử dụng kỹ thuật này khi khoảng thời gian chờ đợi dài Thông thường, nếu critical section chứa lời gọi hàm sleep/schedule hoặc gồm nhiều câu lệnh, thì có thể áp dụng semaphore.

Phương pháp này hoàn toàn phù hợp để áp dụng trong các thread được phép đi ngủ, như kernel thread thông thường hoặc các bottom-half được triển khai bằng workqueue Việc sử dụng kỹ thuật này giúp quản lý trạng thái ngủ của thread một cách hiệu quả, tiết kiệm tài nguyên và tăng hiệu suất xử lý hệ thống Trong thực tế, kernel thread và các bottom-half thực thi thông qua workqueue có thể tận dụng cơ chế ngủ - thức một cách linh hoạt để cân bằng giữa độ đáp ứng và chi phí context switch Do đó, đây là lựa chọn lý tưởng cho các trường hợp mà thread được ngủ và các bottom-half được triển khai bằng workqueue.

G IẢI PHÁP “BUSY - WAITING”

1 Giải pháp phần cứng a) Cấm tắt

Để bảo vệ miền găng và tránh tranh chấp tài nguyên, tiến trình được cho phép cấm mọi ngắt trước khi vào miền găng và phục hồi ngắt ngay sau khi ra khỏi miền găng Khi ngắt đồng hồ được tắt theo đúng trình tự này, hệ thống không thể tạm dừng tiến trình đang xử lý để cấp phát CPU cho tiến trình khác, nhờ đó tiến trình hiện hành có thể thao tác an toàn trong miền găng mà không lo bị tiến trình khác tranh chấp.

- Giải pháp này không được ưa chuộng vì rất thiếu thận trọng khi cho phép tiến trình người dùng được phép thực hiện lệnh cấm ngắt.

Trong hệ thống có nhiều bộ xử lý, lệnh cấm ngắt chỉ tác dụng trên CPU đang thực thi tiến trình; các tiến trình đang chạy trên các CPU khác vẫn có thể truy cập vào miền nhớ được bảo vệ.

- Đây là một giải pháp đòi hỏi sự trợ giúp của cơ chế phần cứng

Nhiều máy tính cung cấp một chỉ thị đặc biệt cho phép kiểm tra và cập nhật nội dung của một vùng nhớ trong một thao tác nguyên tử (không thể phân chia), được gọi là chỉ thị Test-and-Set Lock (TSL) và được định nghĩa như sau: TSL cho phép một tiến trình đọc giá trị tại một địa chỉ và đồng thời ghi một giá trị mới, miễn là hành động này được thực hiện như một thao tác duy nhất để bảo đảm tính nhất quán của dữ liệu và ngăn chặn các xung đột khi nhiều tiến trình truy cập cùng lúc; nhờ tính nguyên tử của nó, TSL trở thành nền tảng cho các cơ chế khóa và đồng bộ hóa trong hệ thống máy tính.

Test-and-Setlock (boolean target) {

Test-and-Setlock = target; target = TRUE;

- Nếu có hai chỉ thị TSL xử lý đồng thời (trên hai bộ xử lý khác nhau), chúng sẽ được xử lý tuần tự Có thể cài đặt giải pháp truy xuất độc quyền với TSL bằng cách sử dụng thêm một biến lock, được khởi gán là FALSE Tiến trình phải kiểm tra giá trị của biến lock trước khi vào miền găng, nếu lock = FALSE, tiến trình có thể vào miền găng. while (TRUE) { while (Test-and-Setlock(lock)); critical-section (); lock = FALSE;

Giống như các giải pháp phần cứng khác, chỉ thị TSL giảm nhẹ công việc lập trình để giải quyết vấn đề đồng bộ hóa Tuy nhiên, việc triển khai chỉ thị TSL sao cho được xử lý một cách không thể phân chia (atomic) vẫn gặp nhiều khó khăn, đặc biệt trên các máy có cấu hình nhiều bộ xử lý (đa lõi).

2 Giả pháp phần mềm a) Sử dụng cở biến hiệu:

- Các tiến trình chia sẻ một biến chung đóng vai trò lock, được khởi động bằng 0.

- Một tiến trình muốn vào miền găng trước tiên phải kiểm tra giá trị của biến lock Nếu lock = 0, tiến trình đặt lock = 1 và đi vào miền găng

- Nếu lock nhân giá trị 1, tiến trình phải chờ bên ngoài miền găng cho đến khi lock = 0.

- Cấu trúc của tiến trình:

- Nhận xét: có thể vi phạm điều kiện cả 2 tiến trình cùng ở trong miền găng tại một thời điểm. b) Sử dụng việc kiểm tra luân phiên

- Giải pháp dành cho hai tiến trình

Mô hình đồng bộ hóa hai tiến trình sử dụng biến chung turn để quản lý lượt vào miền găng Biến turn được khởi động bằng giá trị 0; khi turn = 0, chỉ tiến trình A được vào miền găng, còn khi turn = 1, chỉ tiến trình B được phép vào Biến turn phản ánh lượt tiến trình được vào miền găng và đảm bảo độc quyền truy cập tại mỗi thời điểm.

- Nhận xét: với biện pháp kiểm tra luân phiên có thể ngăn chặn được tình trạng 2 tiến trình cùng vào miền găng Tuy nhiên có thể vi phạm điều kiện một tiến trình có thể bị ngăn vào miền găng bởi

- Kết hợp ý tưởng của hai giải pháp trên: P0, P1 chia sẻ hai biến chung: int turn; //đến phiên ai boolean flag[2] = false; //flag[i] = true => Pi sẵn sàng vào đoạn găng

G IẢI PHÁP “SLEEP AND WAKE UP”

- Khắc phục được nhược điểm của các giải pháp “Busy-Waiting” bằng cách cho một tiến trình chưa đủ điều kiện vào đoạn găng chuyển sang trang thái waiting.

 Tạm khóa tiến trình không cho sử dụng CPU ngay vì tiến tình chỉ sử dụng

CPU khi ở trạng thái running.

 Tiến trình chỉ có thể chuyển sang trạng thái running khi đang ở trạng thái ready.

 Từ bỏ CPU khi chưa được vào Critical-section

 Cần sự hỗ trợ từ hệ điều hành để đánh thức process và đưa process vào trạng thái blocked.

Khi một tiến trình chưa đủ điều kiện vào đoạn găng (critical section), nó gọi sleep để tự khóa và chặn cho tới khi một tiến trình khác gọi wakep giải phóng nó Cơ chế ngủ và tỉnh giấc này giúp đồng bộ hóa truy cập vào khu vực nhạy cảm, ngăn chặn race condition và đảm bảo tiến trình chỉ tiếp tục thực thi khi được phép vào critical section.

 Một tiến trình gọi wakup khi ra khỏi miền găng để đánh thức một tiến trình đang chờ, tạo cơ hội cho tiến trình này vào miền găng.

- Cấu trúc: int busy; //1 nếu miền găng đang bị chiếm, ngược lại là 0 int blocked; //đếm số lượng tiến trình đang bị tạm khóa

- Các giải pháp phổ biến: o Semaphore

1 Giải pháp Monitor Được đề xuất bởi Hoare (1974) và Brinch (1975) Monitor là cơ chế cao hơn được cung cấp bởi ngôn ngữ lập trình. a) Định nghĩa

- Thuật ngữ monitor: giám sát

- Monitor là một cấu trúc dữ liệu có đặc điểm:

 Các biến và cấu trúc dữ liệu bên trong monitor chỉ có thể được thao tác bởi các thủ tục định nghĩa bên trong monitor đó.

 Tại một thời điểm, chỉ có một tiến trình duy nhất được hoạt động bên trong

- Trong một monitor, có thể định nghĩa các biến điều kiện và hai thao tác kèm theo là Wait và Signal như sau: gọi c là biến điều kiện được định nghĩa trong monitor:

Trong cơ chế đồng bộ hóa bằng biến điều kiện, Wait(c) làm cho tiến trình đang thực thi bị block, chuyển sang trạng thái waiting và đẩy vào hàng đợi của biến điều kiện c để chờ tín hiệu từ các tiến trình khác Khi nhận được tín hiệu từ biến điều kiện, tiến trình đang chờ sẽ được thức tỉnh và tiếp tục thực thi.

 Signal(c): giải phóng 1 tiến trình đang bị blocked trên biến điều kiện c.

Nếu có một tiến trình đang bị khóa trong hàng đợi của c, tái kích hoạt tiến trình đó và tiến trình đó sẽ rời khỏi monitor.

 C.queue: danh sách các tiến trình blocked trên c.

(chú thích hình) b) Cấu trúc:

 Tập các procedure thao tác trên tài nguyên chung.

 Khóa loại trừ lẫn nhau.

 Các biến tương ứng với các tài nguyên chung.

 Một số các giả định bất biến nhằm tránh các tình huống tương tranh.

 Một kiểu type hoặc kiểu trừa tượng (abstract type) gồm các dữ liệu private và các phương thức public.

 Monitor type được đặc trưng bởi tập các toán tử của người sử dụng định nghĩa.

 Có các biến xác định các trạng thái; mã lệnh của các procedure thao tác trên các biến này.

 Sử dụng monitor kiểu condition chỉ có 2 toán tử: wait và signal

 Đặc điểm của signal(): o Chỉ đánh thức duy nhất 1 tiến trình đang chờ. o Nếu không có tiến trình chờ, x.signal() không có tác dụng.

 x.signal() khác với signal trong semaphore, signal của semaphore luôn làm thay đổi giá trị (trạng thái) của semaphore. c) Vấn đề sử dụng monitor:

- Monitor không đảm bảo rằng các thứ tự truy xuất trước sẽ được chú ý.

 Một quá trình có thể truy xuất tài nguyên mà không đạt được quyền truy xuất trước đó.

 Một quá trình sẽ không bao giờ giải phóng tài nguyên một khi nó được gán truy xuất tới tài nguyên đó.

 Một quá trình có thể cố gắng giải phóng tài nguyên mà nó không bao giờ yêu cầu.

 Một quá trình có thể yêu cầu cùng tài nguyên hai lần (không giải phóng tài nguyên đó trong lần đầu).

Việc sử dụng monitor trong lập trình đồng bộ gặp nhiều khó khăn, đặc biệt ở khâu xây dựng miền truy cập đồng thời (critical section) an toàn và hiệu quả Thêm vào đó là thách thức khi cần vận dụng đúng các thao tác được định nghĩa bởi người lập trình cấp cao, trong khi nhiều trình biên dịch hiện nay không còn hỗ trợ đầy đủ, khiến cho mã đồng bộ khó duy trì và dễ mắc lỗi Vì vậy, quản lý truy cập tài nguyên và đồng bộ hóa qua monitor đòi hỏi hiểu biết sâu về cơ chế khóa, điều kiện chờ và cách tránh các rủi ro như deadlock, race condition Bài viết này phân tích các điểm yếu phổ biến, gợi ý cách thiết kế monitor hợp lý và những lưu ý kỹ thuật nhằm tối ưu hóa hiệu suất hệ thống.

2 Giải pháp trao đổi thông điệp (message passing):

23 o Semaphore và Monitor có thể giải quyết các vấn đề loại trừ tương hỗ và đồng bộ hóa trên các máy tính có một hoặc nhiều CPU chia sẻ một vùng nhớ chung. o Cơ chế đồng bộ bằng thông điệp có thể giải quyết tình huống này Cơ chế này sử dụng message để thực hiện yêu cầu và nhận thông điệp để vào vùng tranh chấp. a) Giải pháp

- Send (destination, message): Gửi 1 thông điệp đến một tiến trình hay gửi vào hộp thư.

- Receive (source, message): nhận một thông điệp từ một tiến trình hay từ bất kỳ một tiến trình nào, tiến trình gọi sẽ chờ nếu không có thông điệp nào để nhận b) Cơ chế

- Một tiến trình kiểm soát việc sử dụng tài nguyên và nhiều tiến trình khác yêu cầu tài nguyên này.

- Tiến trình có yêu cầu tài nguyên sẽ gửi một thông điệp đến tiến trình

- Khi sử dụng xong tài nguyên, tiến tình gởi một thông điệp khác đến

- Tiến trình kiểm soát, khi nhận được thông điệp yêu cầu tài nguyên, nó sẽ chờ đến khi tài nguyên sẵn sàng để cấp phát c) Cấu trúc

- Cấu trúc tiến trình yêu cầu tài nguyên trong giải pháp message:

BÀI TOÁN READER/WRITER

G IỚI THIỆU BÀI TOÁN

Vấn đề reader-writer liên quan đến một đối tượng được chia sẻ giữa nhiều quy trình, ví dụ như một tệp tin, nơi có các tiến trình đóng vai trò reader chỉ đọc dữ liệu và writer có ý định ghi dữ liệu vào đối tượng; việc đồng thời truy cập của reader và writer có thể gây xung đột và làm mất tính nhất quán của dữ liệu, do đó cần các cơ chế đồng bộ hóa nhằm quản lý quyền truy cập và đảm bảo an toàn cho dữ liệu khi chia sẻ giữa nhiều quy trình.

Vấn đề Reader-Writer được dùng để quản lý đồng bộ hóa nhằm đảm bảo dữ liệu của đối tượng không bị lỗi khi xử lý song song Trong mô hình này, hai reader truy cập cùng một thời điểm thường không gặp vấn đề vì họ chỉ đọc dữ liệu Tuy nhiên, nếu có hai writer đồng thời hoặc reader và writer cùng truy cập vào một đối tượng thì có thể xảy ra xung đột và làm mất tính nhất quán của dữ liệu Vì vậy cần áp dụng cơ chế đồng bộ hóa thích hợp, như khóa đọc-ghi hoặc mutex, để bảo vệ dữ liệu và duy trì tính nhất quán khi có sự truy cập đồng thời.

- Vấn đề đồng bộ hóa gặp phải ở đây là chỉ cho phép một người viết truy cập vào tập dữ liệu tại bất kỳ thời điểm nào có thể cho phép nhiều người đọc cùng một lúc mà không gặp bất kỳ trở ngại nào.

Vấn đề này có thể giải quyết bằng cách sử dụng semaphores.

- Giả sử chúng ta có một khóa trên tập dữ liệu Đầu tiên reader sẽ khóa tập dữ liệu và sau readers đó có thể tiếp tục và bắt đầu đọc Cuối cùng reader sẽ mở khóa khi đọc xong.

- Khi một writer bắt đầu đọc hoặc ngừng đọc, nó sẽ khóa / mở khóa tập dữ liệu cho writers và readers.

- Để kích hoạt đồng bộ hóa quy trình trong vấn đề này, chúng ta có thể sử dụng một giá trị số nguyên và hai nửa hàm.

- Hãy khởi tạo số nguyên read bằng 0, đại diện cho số lần readers truy cập tệp Đây không phải là semaphore, chỉ là một số nguyên.

- Ngoài ra, hãy khởi tạo semaphore S thành 1, nó bảo vệ read biến không bị cập nhật bởi nhiều quy trình.

- Cuối cùng, giả sử chúng ta khởi tạo semaphore write thành 1, nó bảo vệ tập dữ liệu khỏi bị truy cập cùng lúc bởi nhiều writers Vì vậy, mã giả cho writer và reader xử lý:

Trong trường hợp này, tiến trình viết chỉ chờ đợi và nhận tín hiệu duy nhất từ semaphore write Nếu nó có thể lấy được semaphore write, tiến trình sẽ tiếp tục thực thi; ngược lại, thao tác chờ sẽ bị chặn và tiến trình bị đình trệ.

- Vì vậy, các quy trình khác có thể truy cập tập dữ liệu.

Quy trình làm việc của reader phức tạp hơn: điều đầu tiên nó làm là tăng read_count Để làm được điều này, reader cần lấy semaphore S để sửa đổi giá trị read_count, nhằm đảm bảo rằng giá trị này không bị truy cập đồng thời bởi nhiều tiến trình và từ đó tăng cường đồng bộ hóa an toàn giữa các tiến trình trong hệ thống.

Nếu hiện tại không có reader nào khác đang truy cập vào tập dữ liệu, lượt đọc (read_count) sẽ được tăng lên và tập dữ liệu tương ứng sẽ trở thành phiên bản tiếp theo sau khi tăng số lượt đọc Trong trường hợp này, reader sẽ đợi trên semaphore ghi trước khi truy cập tập dữ liệu để đảm bảo rằng không có writer nào đang truy cập cùng lúc.

- Sau khi giải phóng semaphore S, reader tiếp tục và thực hiện thao tác

Trong quá trình đọc dữ liệu, khi reader hoàn tất công việc với tập dữ liệu, nó cần giảm giá trị biến read_count để phản ánh số lượng reader đang truy cập Một bước đồng bộ hóa nữa là reader sẽ giành lại semaphore S, cập nhật lại biến read_count theo trạng thái hiện tại và cuối cùng giải phóng semaphore S, nhằm đảm bảo sự an toàn khi các tác vụ khác tiếp tục truy cập tập dữ liệu và giảm thiểu xung đột giữa các reader và writer.

- Vấn đề reader - writer được chia thành 3 biến thể:

 Biến thể 1: biến thể này ưu tiên reader Khi hai hoặc nhiều reader yêu cầu quyền sử dụng một tài nguyên, chỉ một reader có quyền sử dụng Tuy nhiên, do các reader không sửa đổi dữ liệu nên cần giải quyết vấn đề không để bất kỳ một reader nào phải chờ để sử dụng tài nguyên khi tài nguyên đó đang được sử dụng bởi một reader Trong giải pháp này, mỗi writer phải xác nhận tài nguyên riêng lẻ Điều này có nghĩa là một luồng reader sau đó có thể khóa tất cả các nhà văn tiềm năng và bỏ đói họ Điều này là như vậy, bởi vì sau khi reader đầu tiên khóa tài nguyên, không writer nào có thể khóa nó, trước khi nó được phát hành Và nó sẽ chỉ được phát hành bởi reader cuối cùng Do đó, giải pháp này không đáp ứng được sự công bằng.

Biến thể 2 ưu tiên writer: giải pháp đầu tiên không tối ưu vì một đầu đọc R1 có thể bị khóa, một nhà văn W đang chờ khóa và sau đó một đầu đọc R2 yêu cầu quyền truy cập; nếu R2 vào trước W quá thường xuyên, W sẽ bị đói và cần bắt đầu càng sớm càng tốt Biến thể này thực hiện bằng cách buộc mọi reader phải khóa và giải phóng semaphore đã đọc một cách riêng lẻ, trong khi writer không cần khóa riêng; chỉ writer đầu tiên sẽ khóa phép đọc và sau đó tất cả những writer tiếp theo có thể chỉ cần sử dụng tài nguyên khi nó được giải phóng bởi writer trước, writer cuối cùng phải phát hành semaphore readtry, mở cổng cho reader thử đọc.

Biến thể 3 được xem là công bằng cho cả reader và writer, bởi vì cả hai phía đều có thể bị bỏ đói nếu không có biện pháp phù hợp Thực tế, cả biến thể đều có thể dẫn đến chết đói: giải pháp đầu tiên có thể bỏ đói writer trong hàng đợi, trong khi giải pháp thứ hai có thể bỏ đói reader Vì vậy, giải pháp 3 đôi khi được đề xuất, nhằm bổ sung thêm ràng buộc rằng không có thread nào bị bỏ đói; nghĩa là hoạt động lấy khóa dữ liệu được chia sẻ sẽ luôn kết thúc trong một trạng thái cân bằng giữa các thread.

Không có luồng nào được phép chết đói là nguyên tắc đúng khi các semaphore bảo toàn thứ tự xuất trước nhập sau sau khi chặn và giải phóng các luồng Nếu không duy trì thứ tự này, một luồng viết bị chặn có thể bị chặn vô thời hạn bởi chu kỳ các luồng viết khác làm giảm semaphore trước khi nó có cơ hội thực thi, dẫn đến tình trạng deadlock hoặc starvation.

G IẢI QUYẾT BÀI TOÁN

Nguyên tắc giải quyết bài toán là ai đến trước sẽ được quyền sử dụng tài nguyên trước Đối với các Reader, khi có một reader đang sử dụng tài nguyên và có các Reader khác đang chờ ở phía sau, hệ thống cho phép các Reader đang chờ truy cập tài nguyên theo thứ tự đến Lý do là các Reader không làm thay đổi tài nguyên trong quá trình sử dụng, nên việc cấp quyền truy cập cho các Reader đang chờ không ảnh hưởng đến tính nhất quán của tài nguyên.

Phương án này giải quyết hai vấn đề chính: độc giả đến sau vẫn được tiếp cận tài nguyên trước các tác giả đã có mặt và hiện tượng độc giả chờ đợi một độc giả khác một cách không cần thiết sẽ được loại bỏ.

3 Chương trình bài toán Readers/Writers

Ngày đăng: 06/08/2022, 13:42

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w