Một semaphore phù hợp với mô hình người tiêu dùng sản xuất, mặc dù nó có các ứng dụng khác. Logic chương trình của bạn chịu trách nhiệm đảm bảo rằng số lượng bài đăng phù hợp được thực hiện cho số lần chờ. Nếu bạn đăng một semaphore và không ai đang chờ đợi nó, sau đó khi họ chờ đợi họ tiếp tục ngay lập tức. Nếu vấn đề của bạn là như vậy mà nó có thể được giải thích về giá trị đếm của một semaphore, sau đó nó sẽ được dễ dàng để giải quyết với một semaphore.
Biến điều kiện có thể tha thứ hơn một chút ở một số khía cạnh. Ví dụ, bạn có thể sử dụng cond_broadcast để đánh thức tất cả các bồi bàn, không có nhà sản xuất biết có bao nhiêu người. Và nếu bạn cond_signal một condvar với không ai chờ đợi trên nó thì không có gì xảy ra. Điều này là tốt nếu bạn không biết liệu sẽ có một người nghe thích thú không. Đó cũng là lý do tại sao người nghe nên luôn luôn kiểm tra trạng thái với mutex được tổ chức trước khi chờ đợi - nếu họ không thì họ có thể bỏ lỡ một tín hiệu và không thức dậy cho đến khi một kế tiếp (mà có thể không bao giờ).
Vì vậy, biến điều kiện phù hợp để thông báo cho các bên quan tâm rằng trạng thái đã thay đổi: bạn có được mutex, thay đổi trạng thái, tín hiệu (hoặc phát sóng) condvar và giải phóng mutex. Nếu điều này mô tả vấn đề của bạn, bạn đang ở trong lãnh thổ condvar. Nếu người nghe khác nhau quan tâm đến các tiểu bang khác nhau, bạn có thể phát sóng và họ sẽ lần lượt thức dậy, tìm hiểu xem họ có tìm thấy trạng thái mà họ muốn hay không và nếu không đợi lại.
Nó thực sự rất gnarly để cố gắng loại điều này với một mutex và semaphore một. Vấn đề xảy ra khi bạn muốn thực hiện mutex, kiểm tra một số trạng thái, sau đó chờ trên semaphore để thay đổi. Trừ khi bạn có thể giải phóng nguyên tử mutex và chờ đợi trên semaphore (mà trong pthreads bạn không thể), bạn kết thúc chờ đợi trên semaphore trong khi giữ mutex. Điều này ngăn chặn các mutex, có nghĩa là những người khác không thể lấy nó để làm cho sự thay đổi bạn quan tâm. Vì vậy, bạn sẽ bị cám dỗ để thêm một mutex khác theo cách phụ thuộc vào các yêu cầu cụ thể của bạn. Và có lẽ một semaphore khác. Kết quả thường là mã không chính xác với các điều kiện chủng tộc có hại.
Biến điều kiện thoát khỏi vấn đề này, bởi vì gọi cond_wait tự động giải phóng mutex, giải phóng nó để người khác sử dụng. Các mutex được lấy lại trước khi cond_wait trả về.
IIRC có thể thực hiện một loại condvar chỉ sử dụng semaphores, nhưng nếu mutex bạn đang thực hiện để đi với condvar là cần thiết để có trylock, sau đó nó là một head-scratcher nghiêm trọng, và chờ đợi thời gian được ra . Không được khuyến khích. Vì vậy, đừng cho rằng bất cứ điều gì bạn có thể làm với một condvar có thể được thực hiện với semaphores. Thêm vào đó tất nhiên các mutex có thể có những hành vi tốt đẹp mà semaphores thiếu, chủ yếu là ưu tiên đảo ngược tránh.
Tôi vừa nhận ra rằng "semaphore được khởi tạo đúng" không được xác định. Là semaphore đặt thành 1 hoặc 0? Tôi muốn nói nó nên được thiết lập để 0. Sau đó, không semaphore bảo vệ cam-> tình trạng hay không? – Blaisorblade
Trong đoạn thứ hai, như đã đề cập trong các câu trả lời khác, chuỗi của bạn sẽ bị chặn trong khi mutex không được phát hành. Vì vậy, phương thức 'sem_wait' của bạn sẽ không bao giờ trở lại bởi vì không có luồng nào khác có thể có được mutex và gọi' sem_signal'. Tuy nhiên, tôi sẽ không làm gì nếu tôi phát hành mutex trước 'sem_wait' và yêu cầu nó một lần nữa sau khi chờ đợi. Tôi biết những bước này không phải là nguyên tử, vậy điều gì sẽ xảy ra? – sevenkplus