it-swarm-vi.tech

Sự khác biệt giữa semaphore nhị phân và mutex

Có sự khác biệt nào giữa một semaphore nhị phân và mutex hay về cơ bản chúng giống nhau không?

741
Nitin

Chúng làKHÔNGcùng một thứ. Chúng được sử dụng cho các mục đích khác nhau!
[.___.

Các ngữ nghĩa loại trừ lẫn nhau
[.__.] Các ngữ nghĩa loại trừ lẫn nhau được sử dụng để bảo vệ các tài nguyên được chia sẻ (cấu trúc dữ liệu, tệp, v.v.).

Một semaphore Mutex được "sở hữu" bởi nhiệm vụ đảm nhận nó. Nếu Nhiệm vụ B cố gắng semGive một mutex hiện đang được thực hiện bởi Nhiệm vụ A, cuộc gọi của Nhiệm vụ B sẽ trả về lỗi và không thành công.

Mutexes luôn sử dụng trình tự sau:

[.__.] - SemTake [.__.] - Phần quan trọng [.__.] - SemGive

Đây là một ví dụ đơn giản:

[.__.] Chủ đề A Chủ đề B [.__.] Lấy Mutex [.__.] Dữ liệu truy cập [.___] ] Cung cấp dữ liệu truy cập Mutex <== Unblocks [.__.] ... [.__.] Cung cấp cho Mutex [.__.]

Semaphore nhị phân
[.__.] Semaphore nhị phân giải quyết một câu hỏi hoàn toàn khác:

  • Nhiệm vụ B đang chờ đợi điều gì đó xảy ra (ví dụ một cảm biến bị vấp).
  • Các chuyến đi cảm biến và một tuyến thường xuyên phục vụ ngắt. Nó cần phải thông báo một nhiệm vụ của chuyến đi.
  • Nhiệm vụ B nên chạy và thực hiện các hành động thích hợp cho chuyến đi cảm biến. Sau đó quay lại chờ đợi.

   Task A                      Task B
   ...                         Take BinSemaphore   <== wait for something
   Do Something Noteworthy
   Give BinSemaphore           do something    <== unblocks

Lưu ý rằng với một semaphore nhị phân, B có thể lấy semaphore và A để cung cấp cho nó.
[.__.] Một lần nữa, một semaphore nhị phân KHÔNG bảo vệ tài nguyên khỏi sự truy cập. Hành động cho và nhận một semaphore về cơ bản được tách rời.
[.___.] Nó thường không có ý nghĩa gì đối với cùng một nhiệm vụ để đưa ra và thực hiện trên cùng một semaphore nhị phân.

635
Benoit

Ví dụ về Nhà vệ sinh là một sự tương tự thú vị:

Đột biến:

Là một chìa khóa cho một nhà vệ sinh. Một người có thể có chìa khóa - chiếm nhà vệ sinh - tại thời điểm đó. Khi kết thúc, người này đưa (giải phóng) chìa khóa cho người tiếp theo trong hàng đợi.

Chính thức: "Mutex thường được sử dụng để tuần tự hóa quyền truy cập vào một phần của mã được cấp lại mà không thể được thực thi đồng thời bởi nhiều hơn một luồng. phần đó để đợi cho đến khi luồng đầu tiên thoát khỏi phần đó. " Tham chiếu: Thư viện nhà phát triển Symbian

(Một mutex thực sự là một semaphore có giá trị 1.)

Semaphore:

Là số lượng chìa khóa nhà vệ sinh giống hệt miễn phí. Ví dụ, giả sử chúng ta có bốn nhà vệ sinh với khóa và chìa khóa giống hệt nhau. Số lượng semaphore - số lượng khóa - được đặt thành 4 ở đầu (tất cả bốn nhà vệ sinh đều miễn phí), sau đó giá trị đếm sẽ giảm dần khi mọi người đi vào. không còn khóa miễn phí, số lượng semaphore là 0. Bây giờ, khi eq. một người rời khỏi nhà vệ sinh, semaphore được tăng lên 1 (một khóa miễn phí) và được trao cho người tiếp theo trong hàng đợi.

Chính thức: "Một semaphore hạn chế số lượng người dùng đồng thời của một tài nguyên được chia sẻ lên đến một số lượng tối đa. " Tham chiếu: Thư viện nhà phát triển Symbian

416
dlinsin

Mutex chỉ có thể được phát hành bởi luồng đã thu được nó, trong khi bạn có thể báo hiệu semaphore từ bất kỳ luồng nào khác (hoặc quá trình), vì vậy semaphores phù hợp hơn cho một số vấn đề đồng bộ hóa như nhà sản xuất-người tiêu dùng.

Trên Windows, semaphores nhị phân giống như các đối tượng sự kiện hơn là mutexes.

411
Mladen Janković

Những bài viết hay về chủ đề này:

Từ phần 2:

Mutex tương tự như các nguyên tắc của semaphore nhị phân với một điểm khác biệt đáng kể: nguyên tắc sở hữu. Quyền sở hữu là khái niệm đơn giản mà khi một tác vụ khóa (mua lại) một mutex chỉ có nó mới có thể mở khóa (phát hành) nó. Nếu một tác vụ cố gắng mở khóa một mutex thì nó đã bị khóa (do đó không có riêng của Google) thì gặp phải một điều kiện lỗi và quan trọng nhất là mutex không được mở khóa. Nếu đối tượng loại trừ lẫn nhau không có quyền sở hữu thì không liên quan đến cái mà nó được gọi, nó không phải là một mutex.

139
teki

Vì không có câu trả lời nào ở trên xóa được sự nhầm lẫn, đây là câu trả lời cho sự nhầm lẫn của tôi.

Nói một cách chính xác, một mutex là một cơ chế khóa được sử dụng để đồng bộ hóa quyền truy cập vào tài nguyên. Chỉ có một tác vụ (có thể là một luồng hoặc quá trình dựa trên sự trừu tượng hóa hệ điều hành) có thể có được mutex. Điều đó có nghĩa là sẽ có quyền sở hữu liên quan đến mutex và chỉ chủ sở hữu mới có thể phát hành khóa (mutex).

Semaphore là cơ chế báo hiệu (Tôi đã hoàn thành, bạn có thể thực hiện trên loại tín hiệu). Ví dụ: nếu bạn đang nghe các bài hát (giả sử là một tác vụ) trên điện thoại di động của mình và đồng thời bạn của bạn gọi cho bạn, một ngắt sẽ được kích hoạt theo đó một thói quen dịch vụ ngắt (ISR) sẽ báo hiệu tác vụ xử lý cuộc gọi thức dậy .

Nguồn: http://www.geekforgeek.org/mutex-vs-semaphore/

92
Hemant

Ngữ nghĩa đồng bộ hóa của chúng rất khác nhau:

  • mutexes cho phép tuần tự hóa quyền truy cập vào một tài nguyên nhất định, tức là nhiều luồng chờ một khóa, mỗi lần một luồng và như đã nói trước đó, luồng own khóa cho đến khi hoàn thành: only luồng này có thể mở khóa nó.
  • một semaphore nhị phân là một bộ đếm có giá trị 0 và 1: một tác vụ chặn nó cho đến khi tác vụ any thực hiện một sem_post. Semaphore quảng cáo rằng một tài nguyên có sẵn và nó cung cấp cơ chế để chờ cho đến khi nó được báo hiệu là có sẵn.

Như vậy, người ta có thể thấy một mutex như một mã thông báo được truyền từ nhiệm vụ này sang nhiệm vụ khác và một semaphore là đèn đỏ giao thông (nó báo hiệu ai đó mà nó có thể tiến hành).

37
ppi
  • A Mutex , theo định nghĩa, được sử dụng để tuần tự hóa quyền truy cập vào một phần của mã đăng ký lại không thể được thực thi đồng thời bởi nhiều hơn một luồng.

  • A Semaphore , theo định nghĩa, hạn chế số lượng người dùng đồng thời của một tài nguyên được chia sẻ lên đến số lượng tối đa

  • Một semaphore có thể là Mutex nhưng Mutex không bao giờ có thể là semaphore. Điều này đơn giản có nghĩa là một semaphore nhị phân có thể được sử dụng như Mutex, nhưng Mutex không bao giờ có thể thể hiện chức năng của semaphore.

  • Cả semaphores và Mutex (ít nhất là trên kernel mới nhất) đều không có giá trị trong tự nhiên.
  • Không ai sở hữu semaphores, trong khi Mutex được sở hữu và chủ sở hữu chịu trách nhiệm về chúng. Đây là một sự khác biệt quan trọng từ một quan điểm gỡ lỗi.
  • Trong trường hợp của Mutex, luồng sở hữu Mutex có trách nhiệm giải phóng nó. Tuy nhiên, trong trường hợp semaphores, điều kiện này là không bắt buộc. Bất kỳ luồng nào khác có thể báo hiệu để giải phóng semaphore bằng cách sử dụng s m p s (function.e_ot)

  • Một sự khác biệt khác có thể quan trọng đối với các nhà phát triển là semaphores có hệ thống rộng và vẫn ở dạng tệp trên hệ thống tệp, trừ khi được dọn sạch. Mutex được xử lý trên toàn bộ và được dọn sạch tự động khi quá trình thoát.

  • Bản chất của semaphores làm cho nó có thể sử dụng chúng trong việc đồng bộ hóa quá trình liên quan và không liên quan, cũng như giữa các luồng. Mutex chỉ có thể được sử dụng trong việc đồng bộ hóa giữa các luồng và nhiều nhất là giữa các quy trình liên quan (việc triển khai pthread của kernel mới nhất đi kèm với một tính năng cho phép Mutex được sử dụng giữa các tiến trình liên quan).
  • Theo tài liệu kernel, Mutex nhẹ hơn khi so sánh với semaphores. Điều này có nghĩa là một chương trình có sử dụng semaphore có dung lượng bộ nhớ cao hơn khi so sánh với chương trình có Mutex.
  • Từ góc độ sử dụng, Mutex có ngữ nghĩa đơn giản hơn khi so sánh với semaphores.
35
Varun Chhangani

Ở cấp độ lý thuyết, chúng không khác nhau về mặt ngữ nghĩa. Bạn có thể thực hiện một mutex bằng semaphores hoặc ngược lại (xem tại đây để biết ví dụ). Trong thực tế, việc thực hiện là khác nhau và họ cung cấp các dịch vụ hơi khác nhau.

Sự khác biệt thực tế (về các dịch vụ hệ thống xung quanh chúng) là việc triển khai một mutex nhằm mục đích trở thành một cơ chế đồng bộ hóa nhẹ hơn. Trong Oracle-speak, mutexes được gọi là chốt và semaphores được gọi là waits .

Ở cấp độ thấp nhất, họ sử dụng một số loại nguyên tử test và set cơ chế. Điều này đọc giá trị hiện tại của một vị trí bộ nhớ, tính toán một số loại điều kiện và viết ra một giá trị tại vị trí đó trong một lệnh duy nhất mà không thể bị gián đoạn . Điều này có nghĩa là bạn có thể có được một mutex và kiểm tra xem có ai khác có nó trước bạn không.

Một triển khai mutex điển hình có một quy trình hoặc luồng thực hiện lệnh test-and-set và đánh giá xem có thứ gì khác đã đặt mutex không. Một điểm quan trọng ở đây là không có tương tác với trình lập lịch biểu , vì vậy chúng tôi không biết (và không quan tâm) người đã đặt khóa. Sau đó, chúng tôi hoặc từ bỏ lát cắt thời gian của mình và thử lại khi tác vụ được lên lịch lại hoặc thực hiện a spin-lock . Khóa xoay là một thuật toán như:

Count down from 5000:
     i. Execute the test-and-set instruction
    ii. If the mutex is clear, we have acquired it in the previous instruction 
        so we can exit the loop
   iii. When we get to zero, give up our time slice.

Khi chúng tôi thực hiện xong mã được bảo vệ của mình (được gọi là phần phần quan trọng ), chúng tôi chỉ đặt giá trị mutex thành 0 hoặc bất cứ điều gì có nghĩa là 'rõ ràng'. Nếu nhiều tác vụ đang cố gắng để có được mutex, thì tác vụ tiếp theo sẽ được lên lịch sau khi mutex được phát hành sẽ có quyền truy cập vào tài nguyên. Thông thường, bạn sẽ sử dụng các mutexes để kiểm soát tài nguyên được đồng bộ hóa trong đó chỉ cần truy cập độc quyền trong khoảng thời gian rất ngắn, thông thường để thực hiện cập nhật lên cấu trúc dữ liệu được chia sẻ.

Một semaphore là một cấu trúc dữ liệu được đồng bộ hóa (thường sử dụng một mutex) có số đếm và một số hàm bao cuộc gọi hệ thống tương tác với bộ lập lịch ở độ sâu hơn một chút so với các thư viện mutex. Semaphores được tăng và giảm dần và được sử dụng để block task cho đến khi một cái gì đó khác đã sẵn sàng. Xem Vấn đề của nhà sản xuất/người tiêu dùng để biết ví dụ đơn giản về điều này. Semaphores được khởi tạo cho một số giá trị - một semaphore nhị phân chỉ là một trường hợp đặc biệt trong đó semaphore được khởi tạo thành 1. Đăng lên một semaphore có tác dụng đánh thức một quá trình chờ đợi.

Một thuật toán semaphore cơ bản trông giống như:

(somewhere in the program startup)
Initialise the semaphore to its start-up value.

Acquiring a semaphore
   i. (synchronised) Attempt to decrement the semaphore value
  ii. If the value would be less than zero, put the task on the tail of the list of tasks waiting on the semaphore and give up the time slice.

Posting a semaphore
   i. (synchronised) Increment the semaphore value
  ii. If the value is greater or equal to the amount requested in the post at the front of the queue, take that task off the queue and make it runnable.  
 iii. Repeat (ii) for all tasks until the posted value is exhausted or there are no more tasks waiting.

Trong trường hợp của một semaphore nhị phân, sự khác biệt thực tế chính giữa hai là bản chất của các dịch vụ hệ thống xung quanh cấu trúc dữ liệu thực tế.

EDIT: Như evan đã chỉ ra một cách đúng đắn, spinlocks sẽ làm chậm một bộ vi xử lý. Bạn sẽ chỉ sử dụng một spinlock trên hộp đa bộ xử lý vì trên một bộ xử lý duy nhất, quá trình giữ mutex sẽ không bao giờ thiết lập lại nó trong khi một tác vụ khác đang chạy. Spinlocks chỉ hữu ích trên các kiến ​​trúc đa bộ xử lý.

21

Mặc dù mutex & semaphores được sử dụng làm nguyên thủy đồng bộ hóa, có một sự khác biệt lớn giữa chúng. Trong trường hợp của mutex, chỉ có luồng bị khóa hoặc có được mutex mới có thể mở khóa nó. Trong trường hợp của một semaphore, một luồng chờ trên semaphore có thể được báo hiệu bởi một luồng khác. Một số hệ điều hành hỗ trợ sử dụng mutex & semaphores giữa tiến trình. Thông thường sử dụng là tạo ra trong bộ nhớ chia sẻ.

18
Praveen_Shukla

Mutex: Giả sử chúng ta có chủ đề phần quan trọng mà T1 muốn truy cập thì nó sẽ thực hiện theo các bước dưới đây. T1:

  1. Khóa
  2. Sử dụng phần quan trọng
  3. Mở khóa

Semaphore nhị phân: Nó hoạt động dựa trên tín hiệu chờ đợi và tín hiệu. chờ (s) giảm giá trị "s" xuống một giá trị "s" thường được khởi tạo với giá trị "1", tín hiệu tăng giá trị "s" lên một. nếu giá trị "s" là 1 có nghĩa là không ai đang sử dụng phần quan trọng, khi giá trị bằng 0 có nghĩa là phần quan trọng đang được sử dụng. giả sử luồng T2 đang sử dụng phần quan trọng thì nó sẽ thực hiện theo các bước dưới đây. T2:

  1. wait (s) // giá trị ban đầu là một sau khi gọi chờ, giá trị của nó giảm đi một i.e 0
  2. Sử dụng phần quan trọng
  3. signal (s) // bây giờ giá trị s được tăng lên và nó trở thành 1

Sự khác biệt chính giữa Mutex và Baph semaphore là trong Mutext nếu luồng khóa phần quan trọng thì nó phải mở khóa phần quan trọng, không có luồng nào khác có thể mở khóa nó, nhưng trong trường hợp semaphore nhị phân nếu một luồng khóa phần quan trọng sử dụng chức năng Wait (s) thì giá trị của s trở thành "0" và không ai có thể truy cập nó cho đến khi giá trị của "s" trở thành 1 nhưng giả sử một số tín hiệu gọi luồng khác thì giá trị của "s" trở thành 1 và nó cho phép chức năng khác sử dụng phần quan trọng. do đó trong chủ đề semaphore nhị phân không có quyền sở hữu.

11
Sumit Naik

Bạn rõ ràng sử dụng mutex để khóa dữ liệu trong một luồng được truy cập bởi một luồng khác cùng một lúc. Giả sử rằng bạn vừa gọi lock() và đang trong quá trình truy cập dữ liệu. Điều này có nghĩa là bạn không mong đợi bất kỳ luồng nào khác (hoặc một phiên bản khác của cùng mã luồng) truy cập vào cùng một dữ liệu bị khóa bởi cùng một mutex. Đó là, nếu cùng một mã luồng được thực thi trên một thể hiện luồng khác, chạm vào khóa, thì lock() sẽ chặn luồng điều khiển ở đó. Điều này áp dụng cho một luồng sử dụng một mã luồng khác, cũng đang truy cập cùng một dữ liệu và cũng bị khóa bởi cùng một mutex. Trong trường hợp này, bạn vẫn đang trong quá trình truy cập dữ liệu và bạn có thể mất 15 giây nữa để mở khóa mutex (để luồng khác bị chặn trong khóa mutex sẽ bỏ chặn và sẽ cho phép điều khiển truy cập dữ liệu). Bạn có bằng bất cứ giá nào cho phép một luồng khác chỉ mở khóa cùng một mutex không, và lần lượt, cho phép các luồng đã chờ (chặn) trong khóa mutex để bỏ chặn và truy cập dữ liệu? Hy vọng bạn có những gì tôi đang nói ở đây? Theo, đồng ý theo định nghĩa phổ quát!,

  • với mut mutex, điều này có thể xảy ra. Không có chủ đề khác có thể mở khóa khóa trong chủ đề của bạn
  • với nhóm nhị phân-semaphore, điều này có thể xảy ra. Bất kỳ chủ đề khác có thể mở khóa khóa trong chủ đề của bạn

Vì vậy, nếu bạn rất đặc biệt về việc sử dụng semaphore nhị phân thay vì mutex, thì bạn nên hết sức cẩn thận trong phạm vi phạm vi khóa và khóa. Ý tôi là, mọi luồng điều khiển chạm vào mọi khóa đều đạt được một cuộc gọi mở khóa, cũng không nên là bất kỳ khóa mở khóa đầu tiên nào, thay vào đó, nó phải luôn luôn là khóa đầu tiên.

10
paxi

Mutex được sử dụng cho "Cơ chế khóa". một quá trình tại một thời điểm có thể sử dụng tài nguyên được chia sẻ

trong khi

Semaphores được sử dụng cho "Cơ chế báo hiệu" như "Tôi đã hoàn thành, bây giờ có thể tiếp tục"

10
Jamshad Ahmad

Trên Windows, có hai sự khác biệt giữa mutexes và semaphores nhị phân:

  1. Một mutex chỉ có thể được phát hành bởi luồng có quyền sở hữu, tức là luồng trước đây được gọi là hàm Wait, (hoặc quyền sở hữu khi tạo nó). Một semaphore có thể được phát hành bởi bất kỳ chủ đề.

  2. Một chuỗi có thể gọi một hàm chờ liên tục trên một mutex mà không chặn. Tuy nhiên, nếu bạn gọi một hàm chờ hai lần trên một semaphore nhị phân mà không giải phóng semaphore ở giữa, thì luồng sẽ chặn.

10
Rich

Quan niệm:

Một vài bài báo nói rằng "semaphore nhị phân và mutex giống nhau" hoặc "Semaphore với giá trị 1 là mutex" nhưng sự khác biệt cơ bản là Mutex chỉ có thể được phát hành bởi luồng đã thu được nó, trong khi bạn có thể báo hiệu semaphore từ bất kỳ luồng nào khác

Những điểm chính:

• Một chuỗi có thể có được nhiều hơn một khóa (Mutex).

• Một mutex có thể bị khóa nhiều lần chỉ khi một mutex đệ quy, ở đây khóa và mở khóa cho mutex phải giống nhau

• Nếu một chuỗi đã khóa mutex, cố gắng khóa mutex lại, nó sẽ vào danh sách chờ của mutex đó, dẫn đến bế tắc.

• semaphore nhị phân và mutex giống nhau nhưng không giống nhau.

• Mutex hoạt động tốn kém do các giao thức bảo vệ liên quan đến nó.

• Mục đích chính của mutex là đạt được quyền truy cập nguyên tử hoặc khóa tài nguyên

9
Saurabh Sinha

A Mutex kiểm soát quyền truy cập vào một tài nguyên được chia sẻ. Nó cung cấp các hoạt động để có được () truy cập vào tài nguyên đó và phát hành () khi hoàn thành.

A Semaphore kiểm soát quyền truy cập vào nhóm tài nguyên được chia sẻ. Nó cung cấp các hoạt động cho Chờ () cho đến khi một trong các tài nguyên trong nhóm trở nên khả dụng và Tín hiệu () khi được đưa trở lại nhóm.

Khi số lượng tài nguyên mà Semaphore bảo vệ lớn hơn 1, nó được gọi là Đếm Semaphore . Khi nó kiểm soát một tài nguyên, nó được gọi là Boolean Semaphore . Một semaphore boolean tương đương với một mutex.

Do đó, Semaphore là một mức độ trừu tượng cao hơn Mutex. Một Mutex có thể được thực hiện bằng cách sử dụng Semaphore nhưng không phải là cách khác.

8
Charan

Câu hỏi được sửa đổi là - Sự khác biệt giữa một mutex và một semaphore "nhị phân" trong "Linux" là gì?

Trả lời: Sau đây là những khác biệt - i) Phạm vi - Phạm vi của mutex nằm trong một không gian địa chỉ quy trình đã tạo ra nó và được sử dụng để đồng bộ hóa các luồng. Trong khi đó semaphore có thể được sử dụng trên không gian quá trình và do đó nó có thể được sử dụng để đồng bộ hóa quá trình.

ii) Mutex nhẹ và nhanh hơn semaphore. Futex thậm chí còn nhanh hơn.

iii) Mutex có thể được mua lại bởi cùng một luồng thành công nhiều lần với điều kiện nó sẽ giải phóng nó cùng một số lần. Chủ đề khác cố gắng để có được sẽ chặn. Trong khi đó trong trường hợp semaphore nếu cùng một quá trình cố gắng để có được nó một lần nữa thì nó sẽ bị chặn vì nó chỉ có thể được lấy một lần.

6
Mickey

Mutex hoạt động để chặn khu vực quan trọng, nhưng Semaphore hoạt động rất tốt.

6
Askkan

Khác biệt giữa Semaphore nhị phân và Mutex: OWNERSHIP: Semaphores có thể được báo hiệu (đăng) ngay cả từ một chủ sở hữu không hiện tại. Nó có nghĩa là bạn có thể chỉ cần đăng từ bất kỳ chủ đề khác, mặc dù bạn không phải là chủ sở hữu.

Semaphore là một tài sản công cộng trong quá trình, Nó có thể được đăng đơn giản bởi một chủ đề không phải chủ sở hữu. Vui lòng đánh dấu sự khác biệt này trong các chữ cái BÓNG, nó có nghĩa là rất nhiều.

5
buddingspacer

http://www.geekforgeek.org/archives/9102 thảo luận chi tiết.

Mutex là cơ chế khóa được sử dụng để đồng bộ hóa quyền truy cập vào tài nguyên. Semaphore là cơ chế báo hiệu.

Tùy thuộc vào lập trình viên nếu anh ấy/cô ấy muốn sử dụng semaphore nhị phân thay cho mutex.

5
user1852497

Trong cửa sổ sự khác biệt là như dưới đây. MUTEX : quá trình thực hiện thành công chờ phải thực thi một tín hiệu và ngược lại. CÁC HÌNH ẢNH BINary : Các quy trình khác nhau có thể thực thi chờ hoặc signal hoạt động trên một semaphore.

4
ajay bidari

Ngoài thực tế là các mutexes có chủ sở hữu, hai đối tượng có thể được tối ưu hóa cho việc sử dụng khác nhau. Mutexes được thiết kế để được tổ chức chỉ trong một thời gian ngắn; vi phạm điều này có thể gây ra hiệu suất kém và lập kế hoạch không công bằng. Ví dụ, một luồng đang chạy có thể được phép có được một mutex, mặc dù một luồng khác đã bị chặn trên nó. Semaphores có thể cung cấp công bằng hơn, hoặc công bằng có thể bị buộc sử dụng một số biến điều kiện.

4
jilles

Khái niệm này là rõ ràng với tôi sau khi đi qua bài viết trên. Nhưng có một số câu hỏi còn sót lại. Vì vậy, tôi đã viết đoạn mã nhỏ này.

Khi chúng ta cố gắng đưa ra một semaphore mà không lấy nó, nó sẽ đi qua. Nhưng, khi bạn cố gắng đưa ra một mutex mà không lấy nó, nó đã thất bại. Tôi đã thử nghiệm điều này trên nền tảng Windows. Cho phép USE_MUTEX chạy cùng mã bằng MUTEX.

#include <stdio.h>
#include <windows.h>
#define xUSE_MUTEX 1
#define MAX_SEM_COUNT 1

DWORD WINAPI Thread_no_1( LPVOID lpParam );
DWORD WINAPI Thread_no_2( LPVOID lpParam );

HANDLE Handle_Of_Thread_1 = 0;
HANDLE Handle_Of_Thread_2 = 0;
int Data_Of_Thread_1 = 1;
int Data_Of_Thread_2 = 2;
HANDLE ghMutex = NULL;
HANDLE ghSemaphore = NULL;


int main(void)
{

#ifdef USE_MUTEX
    ghMutex = CreateMutex( NULL, FALSE, NULL);
    if (ghMutex  == NULL) 
    {
        printf("CreateMutex error: %d\n", GetLastError());
        return 1;
    }
#else
    // Create a semaphore with initial and max counts of MAX_SEM_COUNT
    ghSemaphore = CreateSemaphore(NULL,MAX_SEM_COUNT,MAX_SEM_COUNT,NULL);
    if (ghSemaphore == NULL) 
    {
        printf("CreateSemaphore error: %d\n", GetLastError());
        return 1;
    }
#endif
    // Create thread 1.
    Handle_Of_Thread_1 = CreateThread( NULL, 0,Thread_no_1, &Data_Of_Thread_1, 0, NULL);  
    if ( Handle_Of_Thread_1 == NULL)
    {
        printf("Create first thread problem \n");
        return 1;
    }

    /* sleep for 5 seconds **/
    Sleep(5 * 1000);

    /*Create thread 2 */
    Handle_Of_Thread_2 = CreateThread( NULL, 0,Thread_no_2, &Data_Of_Thread_2, 0, NULL);  
    if ( Handle_Of_Thread_2 == NULL)
    {
        printf("Create second thread problem \n");
        return 1;
    }

    // Sleep for 20 seconds
    Sleep(20 * 1000);

    printf("Out of the program \n");
    return 0;
}


int my_critical_section_code(HANDLE thread_handle)
{

#ifdef USE_MUTEX
    if(thread_handle == Handle_Of_Thread_1)
    {
        /* get the lock */
        WaitForSingleObject(ghMutex, INFINITE);
        printf("Thread 1 holding the mutex \n");
    }
#else
    /* get the semaphore */
    if(thread_handle == Handle_Of_Thread_1)
    {
        WaitForSingleObject(ghSemaphore, INFINITE);
        printf("Thread 1 holding semaphore \n");
    }
#endif

    if(thread_handle == Handle_Of_Thread_1)
    {
        /* sleep for 10 seconds */
        Sleep(10 * 1000);
#ifdef USE_MUTEX
        printf("Thread 1 about to release mutex \n");
#else
        printf("Thread 1 about to release semaphore \n");
#endif
    }
    else
    {
        /* sleep for 3 secconds */
        Sleep(3 * 1000);
    }

#ifdef USE_MUTEX
    /* release the lock*/
    if(!ReleaseMutex(ghMutex))
    {
        printf("Release Mutex error in thread %d: error # %d\n", (thread_handle == Handle_Of_Thread_1 ? 1:2),GetLastError());
    }
#else
    if (!ReleaseSemaphore(ghSemaphore,1,NULL) )      
    {
        printf("ReleaseSemaphore error in thread %d: error # %d\n",(thread_handle == Handle_Of_Thread_1 ? 1:2), GetLastError());
    }
#endif

    return 0;
}

DWORD WINAPI Thread_no_1( LPVOID lpParam ) 
{ 
    my_critical_section_code(Handle_Of_Thread_1);
    return 0;
}


DWORD WINAPI Thread_no_2( LPVOID lpParam ) 
{
    my_critical_section_code(Handle_Of_Thread_2);
    return 0;
}
4
Raghav Navada

Mặc dù một semaphore nhị phân có thể được sử dụng như một mutex, một mutex là một trường hợp sử dụng cụ thể hơn, trong đó chỉ có quá trình khóa mutex được cho là để mở khóa nó. Hạn chế quyền sở hữu này giúp bảo vệ chống lại:

  • Tình cờ phát hành
  • Bế tắc đệ quy
  • Nhiệm vụ bế tắc

Những ràng buộc này không phải lúc nào cũng có mặt vì chúng làm giảm tốc độ. Trong quá trình phát triển mã của bạn, bạn có thể kích hoạt các kiểm tra này tạm thời.

ví dụ. bạn có thể bật thuộc tính Kiểm tra lỗi trong mutex của bạn. Lỗi khi kiểm tra mutexes trả về EDEADLK nếu bạn cố khóa cùng một lần hai lần và EPERM nếu bạn mở khóa một mutex không phải của bạn.

pthread_mutex_t mutex;
pthread_mutexattr_t attr;
pthread_mutexattr_init (&attr);
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
pthread_mutex_init (&mutex, &attr);

Sau khi khởi tạo, chúng ta có thể đặt các kiểm tra này vào mã của mình như sau:

if(pthread_mutex_unlock(&mutex)==EPERM)
 printf("Unlock failed:Mutex not owned by this thread\n");
3
Adi06411

Mutex được sử dụng để bảo vệ mã và dữ liệu nhạy cảm, semaphore được sử dụng để đồng bộ hóa. Bạn cũng có thể sử dụng thực tế với bảo vệ mã nhạy cảm, nhưng có thể có rủi ro giải phóng sự bảo vệ của luồng khác bằng thao tác V.So Chính sự khác biệt giữa bi-semaphore và mutex là quyền sở hữu nhà vệ sinh và khóa cửa, nhưng người khác có thể vào bằng cách yêu cầu quản trị viên mở cửa, thật nực cười.

2
mannnnerd

Mutex

Mutexes thường được sử dụng để tuần tự truy cập vào một phần của mã đăng ký lại mà không thể được thực thi đồng thời bởi nhiều hơn một luồng. Một đối tượng mutex chỉ cho phép một luồng vào một phần được kiểm soát, buộc các luồng khác cố gắng truy cập vào phần đó để đợi cho đến khi luồng đầu tiên thoát khỏi phần đó. Việc sử dụng mutex là để bảo vệ tài nguyên được chia sẻ có thể gây nguy hiểm tác dụng phụ ngoài ý muốn. Bất kỳ hai nhiệm vụ RTOS nào hoạt động ở các mức độ ưu tiên khác nhau và phối hợp thông qua một mutex, tạo cơ hội cho đảo ngược ưu tiên . Mutex hoạt động trong không gian người dùng .

Semaphore

Semaphore là một cơ chế báo hiệu. Semaphore hạn chế số lượng người dùng đồng thời của một tài nguyên được chia sẻ lên đến số lượng tối đa. Các chủ đề có thể yêu cầu quyền truy cập vào tài nguyên (giảm semaphore) và có thể báo hiệu rằng chúng đã kết thúc bằng cách sử dụng tài nguyên (tăng semaphore). Nó cho phép số lượng luồng truy cập vào các tài nguyên được chia sẻ. Việc sử dụng chính xác một semaphore là để báo hiệu từ một nhiệm vụ này sang một nhiệm vụ khác cũng có thể được sử dụng để báo hiệu từ một thói quen dịch vụ ngắt (ISR) cho một nhiệm vụ. Báo hiệu một semaphore là một hành vi RTOS không chặn và do đó ISR an toàn. Bởi vì kỹ thuật này giúp loại bỏ nhu cầu dễ bị lỗi để vô hiệu hóa các ngắt ở cấp độ nhiệm vụ. Điều này hoạt động trong không gian hạt nhân .

1
Gopika BG

Mutexes có quyền sở hữu, không giống như semaphores. Mặc dù bất kỳ luồng nào, trong phạm vi của một mutex, đều có thể nhận được một mutex đã được mở khóa và khóa truy cập vào cùng một phần quan trọng của mã, chỉ luồng đã khóa một mutex nên mở khóa nó .

1
laksbv

Mutex và semaphore nhị phân đều có cùng một cách sử dụng, nhưng trong thực tế, chúng khác nhau.

Trong trường hợp của mutex, chỉ có luồng đã bị khóa mới có thể mở khóa. Nếu bất kỳ chủ đề khác đến để khóa nó, nó sẽ chờ.

Trong trường hợp semaphone, đó không phải là trường hợp. Semaphore không được gắn với một ID chủ đề cụ thể.

1
Neeraj Sh

Câu trả lời có thể phụ thuộc vào hệ điều hành đích. Ví dụ: ít nhất một triển khai RTOS tôi quen thuộc sẽ cho phép nhiều thao tác "nhận" tuần tự đối với một mutex OS duy nhất, miễn là tất cả chúng đều nằm trong cùng một bối cảnh luồng. Bội số phải được thay thế bằng số lần đặt bằng nhau trước khi một luồng khác sẽ được phép lấy mutex. Điều này khác với các semaphores nhị phân, chỉ cho phép một lần lấy duy nhất tại một thời điểm, bất kể bối cảnh luồng.

Ý tưởng đằng sau loại mutex này là bạn bảo vệ một đối tượng bằng cách chỉ cho phép một bối cảnh duy nhất sửa đổi dữ liệu tại một thời điểm. Ngay cả khi luồng nhận được mutex và sau đó gọi một hàm sửa đổi thêm đối tượng (và nhận/đặt mutex bảo vệ xung quanh các hoạt động của chính nó), các hoạt động vẫn sẽ an toàn vì tất cả đều diễn ra trong một luồng.

{
    mutexGet();  // Other threads can no longer get the mutex.

    // Make changes to the protected object.
    // ...

    objectModify();  // Also gets/puts the mutex.  Only allowed from this thread context.

    // Make more changes to the protected object.
    // ...

    mutexPut();  // Finally allows other threads to get the mutex.
}

Tất nhiên, khi sử dụng tính năng này, bạn phải chắc chắn rằng tất cả các truy cập trong một luồng thực sự an toàn!

Tôi không chắc mức độ phổ biến của phương pháp này, hoặc liệu nó có áp dụng bên ngoài các hệ thống mà tôi quen thuộc không. Để biết ví dụ về loại mutex này, hãy xem ThreadX RTOS.

1
Casey Barker

Như nhiều người ở đây đã đề cập, một mutex được sử dụng để bảo vệ một đoạn mã quan trọng (phần quan trọng của AKA.) Bạn sẽ có được mutex (khóa), nhập phần quan trọng và giải phóng mutex (mở khóa) tất cả trong cùng một luồng .

Trong khi sử dụng semaphore, bạn có thể tạo một luồng chờ trên một semaphore (nói luồng A), cho đến khi một luồng khác (nói luồng B) hoàn thành bất kỳ nhiệm vụ nào, và sau đó đặt Semaphore cho luồng A dừng chờ và tiếp tục nhiệm vụ của nó.

1
Dom045

Vấn đề cơ bản là đồng thời. Có nhiều hơn một luồng kiểm soát. Hãy suy nghĩ về hai quá trình sử dụng một bộ nhớ chia sẻ. Bây giờ chỉ có một quá trình có thể truy cập vào bộ nhớ chia sẻ tại một thời điểm. Nếu có nhiều quá trình truy cập vào bộ nhớ dùng chung cùng một lúc, nội dung của bộ nhớ dùng chung sẽ bị hỏng. Nó giống như một đường ray xe lửa. Chỉ có một chuyến tàu có thể chạy trên nó, nếu không sẽ có một tai nạn. Vì vậy, có một cơ chế báo hiệu, mà một tài xế kiểm tra. Nếu tín hiệu có màu xanh, tàu có thể đi và nếu có màu đỏ thì phải chờ để sử dụng đường ray. Tương tự như vậy trong trường hợp bộ nhớ dùng chung, có một semaphore nhị phân. Nếu semaphore là 1, một quá trình có được nó (làm cho nó 0) và tiếp tục và truy cập nó. Nếu semaphore là 0, quá trình chờ đợi. Chức năng mà semaphore nhị phân phải cung cấp là loại trừ lẫn nhau (hay còn gọi là mutex, nói ngắn gọn) để chỉ một trong nhiều thực thể đồng thời (tiến trình hoặc luồng) loại trừ lẫn nhau. Đó là một điểm cộng mà chúng tôi đã đếm các semaphores, giúp đồng bộ hóa nhiều phiên bản của một tài nguyên.

Loại trừ lẫn nhau là chức năng cơ bản được cung cấp bởi semaphores. Bây giờ trong ngữ cảnh của các chủ đề, chúng ta có thể có một tên và cú pháp khác cho nó. Nhưng khái niệm cơ bản là như nhau: làm thế nào để giữ tính toàn vẹn của mã và dữ liệu trong lập trình đồng thời. Theo tôi, những thứ như quyền sở hữu và kiểm tra liên quan là các sàng lọc được cung cấp bởi việc triển khai.

0
kjohri

"semaphore nhị phân" là một ngôn ngữ lập trình để sử dụng một "semaphore" như "mutex". Rõ ràng có hai sự khác biệt rất lớn:

  1. Cách bạn gọi từng người trong số họ.

  2. Độ dài tối đa của "định danh".

0
ilias iliadis