Semaphore và Mutex là hai cơ chế quản lý tài nguyên chia sẻ trong môi trường Real-Time Operating System (RTOS). Dưới đây là sự phân biệt giữa chúng:
Semaphore:
Định nghĩa: Semaphore là một cơ chế đồng bộ hóa được sử dụng để quản lý quyền truy cập đối với một tài nguyên chia sẻ giữa các “task”.
Số lượng: Semaphore có thể có nhiều hơn một giá trị, thường là các giá trị dương, để biểu thị số lượng tài nguyên có sẵn hoặc quyền truy cập.
Hoạt động: Semaphore giúp “task” yêu cầu và trả lại tài nguyên bằng cách tăng hoặc giảm giá trị của nó. Nếu giá trị của semaphore là 0, “task” yêu cầu truy cập sẽ bị block cho đến khi semaphore trở thành khả dụng.
Sử dụng: Semaphore thường được sử dụng để kiểm soát truy cập đối với tài nguyên không thể chia sẻ cùng lúc bởi nhiều “task”, nhưng số lượng tài nguyên có thể khác nhau.
Mutex (Mutual Exclusion):
Định nghĩa: Mutex là một loại semaphore đặc biệt được sử dụng để quản lý quyền truy cập đối với một tài nguyên duy nhất.
Số lượng: Mutex có hai trạng thái hoặc giá trị, thường được gọi là “locked” và “unlocked”, để chỉ trạng thái tài nguyên đang được sử dụng hoặc không được sử dụng.
Hoạt động: Khi “task” muốn sử dụng tài nguyên, nó cố gắng khóa mutex. Nếu mutex đã được khóa bởi “task” khác, “task” hiện tại sẽ bị block cho đến khi mutex được mở ra (unlocked) bởi “task” khác.
Sử dụng: Mutex thường được sử dụng khi chỉ có một tài nguyên duy nhất mà nhiều “task” có thể truy cập. Mutex đảm bảo rằng chỉ có một “task” duy nhất có thể sử dụng tài nguyên vào một thời điểm.
Ví dụ về Semaphore: Quản lý tài nguyên bàn làm việc trong một văn phòng: Giả sử bạn có một văn phòng với 5 bàn làm việc và nhiều nhân viên cần sử dụng bàn làm việc để làm việc.
Semaphore: officeDesksSemaphore
Số lượng bàn làm việc: 5
Mỗi lần một nhân viên muốn sử dụng bàn làm việc để làm việc, họ phải kiểm tra giá trị của Semaphore (officeDesksSemaphore). Nếu giá trị của Semaphore > 0, tức là còn bàn làm việc khả dụng, họ giảm giá trị của Semaphore xuống 1 và sử dụng một bàn làm việc. Khi hoàn thành công việc, họ tăng giá trị của Semaphore lên 1, cho phép những nhân viên khác tiếp tục sử dụng bàn làm việc.
Giá trị ban đầu của Semaphore (officeDesksSemaphore) trong trường hợp này sẽ là 5, để thể hiện rằng có 5 bàn làm việc khả dụng ban đầu. Khi một nhân viên sử dụng bàn làm việc, giá trị của Semaphore giảm xuống 4, và khi tất cả 5 bàn làm việc đều được sử dụng, giá trị của Semaphore sẽ trở lại 0, và các nhân viên tiếp theo cố gắng yêu cầu sẽ bị block cho đến khi có một bàn làm việc trả lại và giá trị của Semaphore tăng lên trở lại.
Ví dụ về Mutex: Quản lý tài nguyên như máy in trong môi trường đa “task”: Giả sử bạn có một hệ thống mà nhiều “task” cần truy cập vào một máy in để in các tài liệu. Tuy nhiên, bạn muốn đảm bảo chỉ có một “task” duy nhất có thể truy cập vào máy in vào một thời điểm.
Mutex: printerMutex
Máy in: 1 (duy nhất)
Khi một “task” muốn in một tài liệu, nó phải kiểm tra trạng thái của mutex. Nếu mutex đang bị khóa (locked), nghĩa là máy in đang được sử dụng bởi “task” khác, “task” hiện tại sẽ bị block và chờ đến khi mutex được mở ra (unlocked). Khi máy in sẵn sàng, “task” hiện tại sẽ khóa mutex và thực hiện in tài liệu. Sau khi hoàn thành, nó mở mutex để cho “task” khác có thể sử dụng máy in.
Ví dụ: Quản lý truy cập vào nhiều tài nguyên đồng thời trong hệ thống nhúng
Giả sử bạn đang phát triển một hệ thống điều khiển cho một máy in 3D với nhiều bộ phận in 3D. Mỗi bộ phận in 3D có thể cùng lúc chỉ có một “task” được phép truy cập để thực hiện việc in.
chúng ta sử dụng một mảng Semaphore (printPartSemaphores) để quản lý quyền truy cập vào từng bộ phận in 3D riêng biệt. Mỗi “task” được tạo ra để thực hiện việc in 3D (chạy trong hàm PrintTask) đợi Semaphore tương ứng trước khi thực hiện in và sau khi in xong, trả lại Semaphore cho “task” khác có thể thực hiện in trên cùng bộ phận.
Ví dụ này thể hiện cách sử dụng Semaphore để quản lý truy cập đồng thời vào nhiều tài nguyên chia sẻ tương tự nhau trong môi trường RTOS, tương tự như ví dụ về các bàn làm việc mà bạn đã đề cập.
Khi một “task” đang giữ Semaphore và đang thực hiện công việc nào đó, nó thường chỉ trả Semaphore sau khi hoàn thành công việc và không còn cần truy cập vào tài nguyên nữa. Trong trường hợp của ví dụ về máy in, khi “task” đang in 3D đang giữ Semaphore tương ứng với bộ phận in, nó chỉ nên trả Semaphore sau khi hoàn thành việc in.
Nếu “task” chưa hoàn thành việc in nhưng đã trả Semaphore thì có thể gây ra vấn đề, vì nó có thể cho phép “task” khác truy cập vào tài nguyên trước khi công việc hoàn thành, dẫn đến sự cạnh tranh và xung đột dữ liệu.
Vì vậy, thường thì Semaphore sẽ được trả sau khi “task” đã hoàn thành công việc và không còn cần truy cập tài nguyên nữa. Trong trường hợp của máy in, “task” chỉ nên trả Semaphore sau khi việc in 3D hoàn thành và máy in không cần truy cập vào bộ phận in nữa.