Biến thể và biến Mutex/điều kiện là các nguyên tố tốt, hiệu suất rất cao phù hợp để sử dụng ở giữa các luồng hoặc giữa các quy trình.
Tất cả những điều này đều dựa trên ý tưởng (và thường là trên thực tế) của thử nghiệm và thiết lập hoặc các hoạt động nguyên tử khác được thực hiện trên bộ nhớ dùng chung.
Nếu bạn muốn phân phối các quy trình của mình qua mạng, thì các ẩn dụ và các mutex có thể không phù hợp với bạn - chúng chỉ hoạt động trên một máy. Ống và ổ cắm thường có khả năng mở rộng mạng hơn.
Một bản tóm tắt ngắn gọn về mutexes, các biến điều kiện và Cột:
Mutexes
Một mutex là một nguyên thủy có thể được hoặc bị khóa, hoặc mở khóa. Quá trình/chủ đề mà khóa nó phải là một trong những để mở khóa nó. Điều này quyền sở hữu khía cạnh cho phép hệ điều hành áp dụng một số tối ưu hóa thú vị, chẳng hạn như ưu tiên thừa kế và ưu tiên giao thức trần (để tránh ưu tiên đảo ngược). tuy nhiên, mutex không có số được liên kết với nó. Bạn không thể khóa một mutex đã bị khóa, nói chung, và giữ lại bộ nhớ rằng nó đã được "khóa hai lần" (có một số phần mở rộng cho phép điều này, tôi nghĩ, nhưng chúng không có ở mọi nơi)
Biến điều kiện
Một mutex tuyệt vời cho ... tốt, loại trừ MUTual. Nhưng nếu bạn cần chặn một điều kiện liên quan đến đối tượng mà bạn có loại trừ lẫn nhau thì sao? Đối với điều này, bạn sử dụng biến điều kiện hoặc CV. CV được liên kết với một mutex. Ví dụ: giả sử tôi có hàng đợi dữ liệu đầu vào mà các quy trình của tôi muốn truy cập. Một lấy mutex để nó có thể nhìn vào hàng đợi mà không sợ nhiễu. Tuy nhiên, nó tìm thấy hàng đợi trống và muốn chờ đợi một cái gì đó để đi vào hàng đợi. Do đó, nó chờ trên biến điều kiện "hàng đợi không trống". Phần thú vị ở đây là, bởi vì CV được kết hợp với mutex, mutex được tự động mua lại sau khi biến điều kiện được báo hiệu. Vì vậy, một khi quá trình tỉnh dậy sau khi chờ đợi trên CV, nó biết rằng nó có quyền truy cập độc quyền một lần nữa vào hàng đợi. Những gì nó làm không biết là hàng đợi thực sự có bất kỳ thứ gì trên đó - có lẽ hai quá trình chờ đợi trên CV - một thứ xuất hiện - và ưu tiên đầu tiên là "điều" trước khi điều thứ hai đánh thức lên. Vì vậy, bất cứ khi nào bạn sử dụng một CV, bạn cần phải kiểm tra lại tình trạng này, như thế này:
mutex_enter(m);
while (! condition) {
cond_wait(m, c); // drop mutex lock; wait on cv; reacquire mutex
}
//processing related to condition
mutex_exit(m);
Semaphores
OK, đó là mutexes và các biến điều kiện. Semaphores đơn giản hơn. Chúng có thể được tăng lên và giảm đi bởi bất kỳ quá trình nào. Họ có trí nhớ - họ đếm - vì vậy bạn có thể sử dụng chúng để xác định có bao nhiêu tình trạng đã xảy ra. Không phải như vậy với các biến condiiton. Ngoài ra, bởi vì các semaphores có thể được giảm đi bởi một tiến trình và tăng lên bởi một tiến trình khác, chúng không có khía cạnh quyền sở hữu - vì vậy không có sự thừa kế ưu tiên, không thể tránh được ưu tiên đảo ngược ưu tiên.
Bây giờ, cuối cùng - tất cả các cơ chế này đều yêu cầu bộ nhớ dùng chung để thực hiện hiệu quả. Điều này có thể tốt cho bạn, nhưng hãy lưu ý - nếu bạn tin rằng ứng dụng của bạn cuối cùng có thể được phân phối, thì mutexes, biến điều kiện và semaphores có thể không dành cho bạn. Ống và ổ cắm, trong khi chi phí cao hơn nhiều, có khả năng được mở rộng qua mạng khá đơn giản.
Cột POSIX có thể được chia sẻ giữa các quá trình liên quan, trong khi mutexes pthread không thể. – ephemient