Mutex và semaphore trong Java là gì? Sự khác biệt chính là gì?


Câu trả lời:


115

Semaphore có thể được đếm, trong khi mutex chỉ có thể đếm đến 1.

Giả sử bạn có một luồng đang chạy chấp nhận các kết nối máy khách. Luồng này có thể xử lý đồng thời 10 máy khách. Sau đó, mỗi máy khách mới đặt semaphore cho đến khi nó đạt đến 10. Khi Semaphore có 10 cờ, thì luồng của bạn sẽ không chấp nhận các kết nối mới

Mutex thường được sử dụng để bảo vệ công cụ. Giả sử 10 khách hàng của bạn có thể truy cập nhiều phần của hệ thống. Sau đó, bạn có thể bảo vệ một phần của hệ thống bằng mutex để khi 1 máy khách được kết nối với hệ thống con đó, không ai khác có quyền truy cập. Bạn cũng có thể sử dụng Semaphore cho mục đích này. Một mutex là một "Semaphore Loại trừ lẫn nhau" .


4
Điều này hoàn toàn không đúng. Cùng một chuỗi có thể nhập cùng một mutex nhiều hơn một lần, do đó, cần phải duy trì số lượng để đảm bảo các mục nhập & lần thoát được cân bằng.
finnw

1
@finnw, nói chung có hai loại mutexes, đệ quy và không đệ quy. Java có sử dụng kiểu đệ quy theo mặc định không?
edA-qa mort-ora-y

2
@ edA-qa mort-ora-y, thuật ngữ "Mutex" không được sử dụng trong Java VM hoặc thông số kỹ thuật API, vì vậy tôi giả sử nó đề cập đến màn hình được tích hợp trong mọi đối tượng, cũng tương tự như đối tượng Win32 được gọi là Mutex . Điều tương tự cũng áp dụng cho a ReentrantLock. Tất cả những điều này là đệ quy. Tôi không biết bất kỳ ví dụ "thế giới thực" nào về mutex đệ quy không đệ quy (tôi chỉ thấy chúng trong sách giáo khoa) nên tôi đã không xem xét chúng.
finnw

2
Các mutexes không đệ quy có thể được thực hiện bằng cách sử dụng Semaphore với số đếm là một. Điều này có thể hữu ích nếu bạn muốn ngăn các cuộc gọi đệ quy. Điều này có những ứng dụng thực tế, cá nhân tôi đã sử dụng nó trong các dự án lớn để phát hiện các vòng lặp trong mã khởi tạo (A khởi tạo B cố gắng khởi tạo lại A).
Alexander Torstling

1
Trong tiêu chuẩn C ++ 11 (C ++ 0x), mutex là không đệ quy. Họ cũng cung cấp một 'recursive_mutex' riêng biệt cho những người cần điều đó. Tôi biết chúng ta đang nói về Java ở đây, nhưng bây giờ nhiều người trong chúng ta viết mã bằng nhiều ngôn ngữ.
Aditya Kumar Pandey

139

Thật không may, mọi người đã bỏ lỡ sự khác biệt quan trọng nhất giữa semaphore và mutex; khái niệm " quyền sở hữu ".

Semaphore không có khái niệm về quyền sở hữu, điều này có nghĩa là bất kỳ luồng nào cũng có thể giải phóng một semaphore (điều này có thể dẫn đến nhiều vấn đề nhưng có thể giúp "phát hiện cái chết"). Trong khi đó mutex không có khái niệm về quyền sở hữu (tức là bạn chỉ có thể phát hành mutex mà bạn đã có được).
Quyền sở hữu là vô cùng quan trọng để lập trình an toàn cho các hệ thống đồng thời. Tôi luôn khuyên bạn nên sử dụng mutex thay vì semaphore (nhưng có những tác động về hiệu suất).

Mutexes cũng có thể hỗ trợ kế thừa ưu tiên (có thể giúp giải quyết vấn đề đảo ngược ưu tiên) và đệ quy (loại bỏ một loại bế tắc).

Cũng cần chỉ ra rằng có các semaphores "nhị phân" và semaphores "đếm / tổng quát". Semaphore của Java là một semaphore đếm và do đó cho phép nó được khởi tạo với giá trị lớn hơn một (trong khi, như đã chỉ ra, mutex chỉ có thể đếm khái niệm là một). Tính hữu ích của điều này đã được chỉ ra trong các bài viết khác.

Vì vậy, tóm lại, trừ khi bạn có nhiều tài nguyên để quản lý, tôi luôn khuyên bạn nên sử dụng mutex trên semaphore.


1
Câu trả lời của Feabhas khá quan trọng - mutex kiểm tra luồng đang cố gắng giải phóng mutex thực sự sở hữu nó. Tôi đã coi đây là một câu hỏi phỏng vấn nên rất đáng để cố gắng ghi nhớ nó.
andrew pate

40

Mutex về cơ bản là loại trừ lẫn nhau. Chỉ một luồng có thể lấy tài nguyên cùng một lúc. Khi một luồng có được tài nguyên, không có luồng nào khác được phép lấy tài nguyên cho đến khi luồng sở hữu tài nguyên đó giải phóng. Tất cả các luồng đang chờ lấy tài nguyên sẽ bị chặn.

Semaphore được sử dụng để kiểm soát số lượng các luồng đang thực thi. Sẽ có một bộ tài nguyên cố định. Số lượng tài nguyên sẽ giảm đi mỗi khi một luồng sở hữu giống nhau. Khi số lượng semaphore bằng 0 thì không có luồng nào khác được phép lấy tài nguyên. Các chủ đề bị chặn cho đến khi các chủ đề khác sở hữu tài nguyên giải phóng.

Tóm lại, sự khác biệt chính là có bao nhiêu luồng được phép lấy tài nguyên cùng một lúc?

  • Mutex --its MỘT.
  • Semaphore - DEFINED_COUNT của nó, (nhiều như số lượng semaphore)

8

Một mutex được sử dụng để truy cập nối tiếp vào một tài nguyên trong khi một semaphore giới hạn quyền truy cập vào một tài nguyên lên đến một số nhất định. Bạn có thể coi mutex như một semaphore với số lượng truy cập là 1. Dù bạn đặt số lượng semaphore của mình là gì, điều đó có thể các luồng có thể truy cập tài nguyên trước khi tài nguyên bị chặn.



3

Một mutex thường được biết đến như một semaphore nhị phân. Trong khi một semaphore có thể được tạo với bất kỳ số đếm khác không, mutex về mặt khái niệm là một semeaphore với số đếm trên 1.



1

Semaphore :

Một semaphore đếm. Về mặt khái niệm, một semaphore duy trì một tập hợp các giấy phép. Mỗi acquire()khối nếu cần thiết cho đến khi có giấy phép, và sau đó lấy nó. Mỗi release()thêm một giấy phép, có khả năng giải phóng một trình thu thập chặn. Tuy nhiên, không có đối tượng giấy phép thực tế nào được sử dụng; Semaphore chỉ giữ một số lượng có sẵn và hoạt động tương ứng.

Semaphores thường được sử dụng để hạn chế số lượng các luồng hơn là có thể truy cập một số tài nguyên (vật lý hoặc logic)

Java không có API Mutex tích hợp sẵn. Nhưng nó có thể được thực hiện dưới dạng semaphore nhị phân.

Một semaphore được khởi tạo thành một, và được sử dụng sao cho nó chỉ có tối đa một giấy phép khả dụng, có thể dùng như một khóa loại trừ lẫn nhau. Điều này thường được gọi là semaphore nhị phân, vì nó chỉ có hai trạng thái: một giấy phép có sẵn hoặc không có giấy phép.

Khi được sử dụng theo cách này, semaphore nhị phân có thuộc tính (không giống như nhiều triển khai Khóa), rằng "khóa" có thể được giải phóng bởi một luồng không phải chủ sở hữu (vì semaphore không có khái niệm về quyền sở hữu) . Điều này có thể hữu ích trong một số ngữ cảnh chuyên biệt, chẳng hạn như khôi phục bế tắc.

Vì vậy, sự khác biệt chính giữa Semaphore và Mutex:

  1. Semaphore hạn chế số lượng luồng truy cập tài nguyên mà throuhg cho phép. Mutex chỉ cho phép một luồng truy cập tài nguyên.

  2. Không có chủ đề nào sở hữu Semaphore. Các chủ đề có thể cập nhật số lượng giấy phép bằng cách gọi acquire()release()các phương thức. Mutexes chỉ nên được mở khóa bằng sợi giữ khóa.

  3. Khi một mutex được sử dụng với các biến điều kiện, sẽ có một dấu ngoặc kép ngụ ý — rõ ràng phần nào của chương trình đang được bảo vệ d. Điều này không nhất thiết phải xảy ra đối với một semaphore, có thể được gọi là bước đi của lập trình đồng thời — nó mạnh mẽ nhưng quá dễ sử dụng theo cách không có cấu trúc, không xác định.


0

Mutex là semaphore nhị phân. Nó phải được khởi tạo bằng 1 để đáp ứng nguyên tắc First Come First Serve. Điều này đưa chúng ta đến thuộc tính đặc biệt khác của mỗi mutex: người đã giảm , phải là người tăng . Ergo chúng tôi đã có được sự loại trừ lẫn nhau đối với một số tài nguyên.

Bây giờ bạn có thể thấy rằng mutex là một trường hợp đặc biệt của semaphore chung.


0

Đối tượng của Semaphore đồng bộ hóathực hiện một đèn giao thông cổ điển. Đèn giao thông kiểm soát quyền truy cập vào tài nguyên được chia sẻ bởi bộ đếm. Nếu bộ đếm lớn hơn 0, quyền truy cập được cấp; Nếu nó bằng 0, quyền truy cập bị từ chối. Bộ đếm đếm các quyền cho phép truy cập vào tài nguyên được chia sẻ. Sau đó, để truy cập tài nguyên, một luồng phải nhận được sự cho phép từ đèn giao thông. Nói chung, để sử dụng đèn giao thông, luồng muốn truy cập tài nguyên được chia sẻ sẽ cố gắng xin giấy phép. Nếu số lượng đèn giao thông lớn hơn 0, chuỗi sẽ nhận được giấy phép và số lượng đèn giao thông sẽ giảm. Nếu không, chuỗi sẽ bị khóa cho đến khi nó có thể nhận được quyền. Khi luồng không cần truy cập tài nguyên được chia sẻ nữa, nó sẽ giải phóng quyền, do đó, số lượng đèn giao thông được tăng lên. Nếu có một chuỗi khác đang chờ giấy phép, nó có được giấy phép vào thời điểm đó. Lớp Semaphore của Java thực hiện cơ chế này.

Semaphore có hai nhà xây dựng:

Semaphore(int num)
Semaphore(int num, boolean come)

num chỉ định số lượng ban đầu của giấy phép. Sau đó, num chỉ định số luồng có thể truy cập tài nguyên được chia sẻ tại một thời điểm nhất định. Nếu num là một, nó có thể truy cập tài nguyên một luồng tại một thời điểm. Bằng cách thiết lập thành sự thật, bạn có thể đảm bảo rằng các chuỗi bạn đang chờ được cấp quyền theo thứ tự mà họ yêu cầu.


0

Bạn so sánh không thể so sánh được, về mặt kỹ thuật không có sự khác biệt giữa Semaphore và mutex, điều đó không có ý nghĩa. Mutex chỉ là một tên quan trọng giống như bất kỳ tên nào trong logic ứng dụng của bạn, nó có nghĩa là bạn khởi tạo một semaphore ở "1", nó thường được sử dụng để bảo vệ tài nguyên hoặc một biến được bảo vệ để đảm bảo loại trừ lẫn nhau.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.