2012-02-24 56 views
8

Tôi muốn một số làm rõ về mutex và semaphore.
Câu hỏi của tôi là,Mutex và semaphore thực sự làm gì?

  1. mutex Điều gì thực sự làm gì khi a thread cố gắng vào một khu vực bị khóa bởi một mutex, a. nó chờ khóa được thả ra? hoặc b. nó đi vào giấc ngủ cho đến khi khóa được giải phóng. Trong trường hợp đó làm thế nào nó được thức dậy một lần nữa khi khóa được phát hành?
  2. Câu hỏi tương tự như 1, nhưng trong trường hợp này nó là semaphore.
  3. Bạn có thể cho tôi một số mã liên quan đến việc chờ đợi bận rộn trong pthread trong C và cũng là trường hợp chuỗi chuyển sang chế độ ngủ thay vì chờ? ngủ có nghĩa là nó bị chặn hoặc ngủ là một loại chờ đợi bận rộn?
  4. tôi muốn biết một số chương trình nơi các tình huống này được đề cập, ví dụ một số mã nguồn c nơi chờ đợi bận rộn, chặn vv được triển khai.
+0

Đây có phải là bài tập về nhà không? –

+0

Không, tôi đã học về các cơ chế chờ đợi và chặn bận để đồng bộ hóa luồng. Nhưng tôi không chắc chắn về những gì mutex và semaphore nào. –

Trả lời

5

Khi một thread cố gắng để có được một khóa trên một mutex , nếu mutex đó đã được tổ chức thì thông thường nó sẽ sử dụng một cuộc gọi đến hạt nhân OS để chỉ ra rằng nó đang chờ đợi, và sau đó khi thread hiện đang giữ khóa mở khóa mutex thì nó sẽ thực hiện cuộc gọi đến hạt nhân OS để đánh thức một trong những chủ đề chờ đợi.

Điều tương tự cũng áp dụng cho một semaphore, ngoại trừ nó chỉ chặn nếu số được giảm xuống dưới 0, và chủ đề chỉ được đánh thức khi đếm được tăng trở lại trên không. Một bận rộn chờ đợi là nơi bạn không chặn hoặc ngủ khi chờ đợi một cái gì đó, nhưng nhiều lần thăm dò trong một vòng lặp, do đó, bộ vi xử lý luôn luôn bận rộn, nhưng không làm bất cứ điều gì hữu ích. Để thực sự đạt được một sự chờ đợi bận rộn, bạn cần một biến nguyên tử, nhưng chủ đề POSIX không cung cấp một điều như vậy, vì vậy bạn không thể thực sự viết một chờ đợi bận rộn trong pthreads. Gần nhất bạn có thể nhận được là để khóa một mutex, đọc một lá cờ, mở khóa các mutex, vòng lặp nếu cờ không được thiết lập. Điều này liên tục khóa và mở khóa mutex, nhưng không đợi dữ liệu sẵn sàng. Trong trường hợp này, bạn nên sử dụng biến điều kiện thay thế.

Thông thường, bạn nói một chuỗi đang ngủ nếu nó được gọi là một cái gì đó như usleep để tạm ngưng thực thi của chính nó trong một khoảng thời gian nhất định. Điều này trái ngược với việc chặn, nơi nó đang chờ đợi một tín hiệu cụ thể sẽ được cung cấp bởi một luồng khác.

+0

"sau đó nó sẽ thực hiện một cuộc gọi đến hạt nhân hệ điều hành để đánh thức một trong những chủ đề chờ đợi." sau đó nó có nghĩa là chủ đề thực sự đặt vào giấc ngủ khi chờ đợi để mở khóa mutex hoặc giá trị semaphore giảm? chúng không được chờ đợi ở chế độ nền trong một khoảng thời gian cụ thể? –

+2

Cách nó được xử lý là một chi tiết triển khai của hệ điều hành, nhưng có một chuỗi chờ đợi không thường tiêu thụ bất kỳ CPU nào. Nó được thêm vào một danh sách các chủ đề chờ đợi bởi hệ điều hành, và chỉ đánh thức khi được báo hiệu bởi mutex đang được mở khóa. –

+0

Bạn có thể đạt được sự bận rộn chờ đợi bằng cách sử dụng pthreads, đó là lý do tại sao có các chức năng pthread_spin_ {init, destroy, lock, unlock, trylock}. – janneb

-1

Nói cách đơn giản Mutex là dành cho nội dung khi bạn quan tâm đến 1 khóa .... semaphore là dành cho nhiều khóa .. Tôi sẽ cố gắng gửi cho bạn các mẫu. Tôi nhớ tôi đã có một số bài tập liên quan đến semaphore mutex và trong C .. Theo như khái niệm là có liên quan này là một cái gì đó hài hước ở đây http://geekswithblogs.net/shahed/archive/2006/06/09/81268.aspx :)

Cảm ơn

+0

Semaphore cũng có thể được sử dụng cho một khóa duy nhất. –

0

Nó phụ thuộc vào loại mutex (triển khai sao lưu), một số sẽ bận quay vòng, những người khác sẽ chỉ ngủ đối tượng luồng hạt, sau đó sẽ được đánh thức khi mutex được cập nhật và một số là lai của cả hai (động cơ Nguồn của Valve sử dụng các động cơ lai). Các đặc tính của nó cũng phụ thuộc vào thời gian và tần suất cần phải vượt qua các rào cản không gian của người dùng/hạt nhân, vì đôi khi điều này có thể tốn kém hơn nhiều so với chỉ kéo dài hơn một chút (xem this nếu bạn muốn tìm hiểu thêm về khía cạnh xoay vòng và ngủ).

Mutexes thường dành cho mục nhập chuỗi đơn tại một thời điểm (mặc dù chúng có thể hỗ trợ mục nhập đệ quy theo cùng một chuỗi).Mặt khác, các phép ẩn dụ chỉ cho phép các chủ đề n cố gắng giành được nó (xem bài viết này MSDN ghi đè hoặc this so sánh Intel writeup).

Ngủ một chuỗi thường có nghĩa là nó từ bỏ thời gian tính toán phân bổ của nó cho đến khi sẵn sàng để được đánh thức và trình lên lịch hệ điều hành cung cấp cho nó một lát thời gian khác. các ví dụ tốt nhất mà bạn có khả năng tìm thấy sẽ thực sự nằm trong nguồn nhân Linux (hoặc bất kỳ hệ điều hành mã nguồn mở nào khác cho vấn đề đó).

+0

Xin chào, tôi đặc biệt quan tâm đến việc thực hiện đề xuất posix trong linux C. Vì vậy, từ quan điểm posix thì mutex và semaphore thực sự làm gì? Ví dụ nếu tôi viết một mã trong C trong đó một số dữ liệu được chia sẻ bị khóa với mutex, khi các chủ đề khác truy cập, nó sẽ đợi? hoặc chỉ bị chặn phát hành tài nguyên của nó? và điều gì sẽ xảy ra trong trường hợp semaphore. nếu thread đang chặn thì làm thế nào quay và bận chờ đợi được thực hiện trong posix C? Các điều kiện có thay đổi theo cách duy nhất không? –

0
  1. Điều gì thực sự xảy ra khi chuỗi cố gắng nhập khu vực bị khóa bằng mutex, a. nó chờ khóa được thả ra? hoặc b. nó đi đến ngủ cho đến khi khóa được giải phóng. Trong trường hợp đó làm thế nào nó được thức dậy một lần nữa khi khóa được phát hành?

Khi một chủ đề cố gắng lấy khóa mutex, nó bị kẹt và chỉ trả về khi khóa được cấp cho chuỗi đó. Khóa được công nhận bởi hệ điều hành, do đó, hệ điều hành biết rằng cho đến khi một khóa như vậy là có sẵn để cung cấp cho thread - nó không có gì khác để làm. Chủ đề được đỗ bên trong hệ điều hành. Nó chỉ là hệ điều hành mà biết rằng bây giờ các chủ đề có quyền sở hữu nó đi lại vào giấc ngủ. Trong một hệ thống CPU đơn lẻ, tại chính trường hợp đó nếu một số tiến trình khác được bật, khóa mutex sẽ chỉ trả về khi luồng có cả hai - CPU cũng có sẵn được khóa!

Lưu ý: khi bạn làm fwrite hoặc select điều tương tự cũng xảy ra. Kể từ khi hệ điều hành biết rằng IO tương ứng sẽ mất thời gian, thread trở nên nhàn rỗi. Khi dữ liệu đến, luồng sẽ trở thành runnable.

  1. Câu hỏi tương tự như 1, nhưng trong trường hợp này là semaphore. Bạn có thể cho tôi một số mã liên quan đến việc chờ đợi bận rộn trong pthread trong C, và cũng là một trường hợp nơi mà chủ đề đi ngủ thay vì chờ đợi? ngủ nghĩa là bị chặn hoặc ngủ là một kiểu chờ đợi bận rộn khác?

Trong cả hai trường hợp, KHÔNG có chờ đợi bận. Nếu có ai bận rộn chờ đợi để giết thời gian cho đến khi bạn nhận được khóa - bạn đã thực sự thất bại mục đích của khóa! Hãy xem xét điều này, hãy nói rằng chúng tôi có trường hợp CPU đơn nghiêm ngặt (và một hệ điều hành ngu ngốc). Vì vậy, những gì xảy ra là, thread 1 cố gắng để có được khóa, kể từ khóa nằm với thread B để thread A bắt đầu làm bận rộn chờ đợi. Do đó, CPU không bao giờ được giải phóng khỏi luồng A và luồng B không bao giờ có cơ hội thực hiện trên CPU - cuối cùng cả hai luồng đều trong tình trạng vô dụng. Khóa không làm bất cứ điều gì trên đối tượng thread. Nhưng quá trình khóa luôn đậu các chủ đề

+0

Xin chào, được rồi, ý của bạn là nếu có nhu cầu kéo sợi, tôi phải thực hiện rõ ràng việc chờ đợi bận rộn đó, tức là với một số biến hoặc biến điều kiện đúng không? Tôi có nghĩa là mutex và semaphore không cho phép chủ đề để chờ đợi, phải không? ví dụ nếu semaphore được khởi tạo với 5, thì khi nó là 5, các chủ đề khác sẽ được đưa vào giấc ngủ bởi hệ điều hành cho đến khi semaphore giảm từ 5, và sau đó chủ đề sẽ được đánh thức bởi hệ điều hành, tôi có đúng không? –

+0

@Pbasak khi thread đạt được quyền truy cập của mutex (hoặc nếu điều kiện semaphore được đáp ứng), thread bây giờ là 'runnable' - có thể có nhiều runnable đề trong một hệ thống để phụ thuộc vào các khía cạnh khác của lịch trình hệ điều hành. Bản thân việc mua lại Mutex không kiểm soát các chủ đề khác trong hệ thống - nhưng số của bạn hiện đang trong hàng đợi đang hoạt động. –

0

chờ, ngủ, ngăn chặn, tất cả các ý nghĩa giống nhau:

  1. Các chủ đề thực hiện cuộc gọi hệ thống (có được một mutex hoặc semaphore, chờ đợi một thời gian, bất cứ điều gì)

  2. Hệ điều hành có quyền kiểm soát, chạy bộ lập lịch, đánh dấu chuỗi đang chờ tài nguyên, cập nhật trạng thái của các chủ đề khác, sau đó kiểm soát chuỗi đã sẵn sàng để chạy. Nếu có nhiều hơn một luồng đã sẵn sàng để chạy, một luồng được chọn theo chính sách lập lịch biểu.

  3. Ngay sau khi tài nguyên được cung cấp (thông qua một cuộc gọi hệ thống khác được tạo bởi một luồng khác), trình lên lịch cập nhật trạng thái của chuỗi cũ để chờ tài nguyên sẵn sàng chạy và chuỗi được kiểm soát ngay sau đó vì chính sách lịch biểu quyết định như vậy.

Miễn là chuỗi đang chờ tài nguyên, nó không tiêu thụ CPU. Không có bỏ phiếu từ một phần của nó.

3

Hãy xem tại địa chỉ: https://stackoverflow.com/a/24582076/3163691

Vâng, cả hai mutexsemaphore được đồng bộ hóa đối tượng hạt nhân mà khi a thread cố gắng Acquire một trong số họ, chủ đề này được đưa vào ngủ nếu đối tượng đó đã thuộc sở hữu của chủ đề khác.

Như bạn đã đoán ra, đây ngủ là một tính năng rất quan trọng vì nó cho phép chủ đề khác để làm công việc hữu ích hơn là chỉ 'looping/bỏ phiếu'.

Các ngủ các chủ đề kết thúc khi các chủ đề những người sở hữu đối tượng phát hành nó.

[OS Scheduler không đưa ra bất cứ thực hiện lát để đề ngủ].

Contrast nó với một khóa & spinlocknơi a thread là trong một 'looping/bận-chờ đợi' tình trạng lãng phí thời gian CPU quý làm gần như không có gì . Do đó, nên tránh vòng quay trong Mã người dùng. Sử dụng một phần quan trọng, mutex hoặc semaphore thay thế !.

Như bạn có thể thấy từ liên kết ở trên, cả hai đối tượng đều khác nhau và nên được sử dụng trong đúng ngữ cảnh phù hợp nhất.

nghĩ về một mutex như một khóa cho phép chỉ một thread để sở hữu nó. Và nó có nhiều thuộc tính an toàn (quyền sở hữu, thông báo chấm dứt, đệ quy, v.v.).

Và, suy nghĩ của một semaphore như một khóa cho phép chỉ một số quy định của đề để sở hữu nó. Tuy nhiên, nó không có nhiều thuộc tính hữu ích của một số mutex.

Hy vọng điều này sẽ hữu ích.

Các vấn đề liên quan