Semaphore - Công dụng của số đếm ban đầu là gì?


91

http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim.aspx

Để tạo một semaphore, tôi cần cung cấp số lượng ban đầu và số lượng tối đa. MSDN nói rằng số lượng ban đầu là -

Số lượng yêu cầu ban đầu cho semaphore có thể được cấp đồng thời.

Trong khi nó nói rằng số lượng tối đa là

Số lượng yêu cầu tối đa cho semaphore có thể được cấp đồng thời.

Tôi có thể hiểu rằng số lượng tối đa là số luồng tối đa có thể truy cập đồng thời một tài nguyên. Nhưng, việc sử dụng số đếm ban đầu là gì?

Nếu tôi tạo một semaphore với số lượng ban đầu là 0 và số lượng tối đa là 2, không có chủ đề nào trong chuỗi threadpool của tôi có thể truy cập tài nguyên. Nếu tôi đặt số lượng ban đầu là 1 và số lượng tối đa là 2 thì chỉ luồng hồ bơi luồng mới có thể truy cập tài nguyên. Chỉ khi tôi đặt cả số lượng ban đầu và số lượng tối đa là 2, 2 luồng mới có thể truy cập tài nguyên đồng thời. Vì vậy, tôi thực sự bối rối về ý nghĩa của số lượng ban đầu?

SemaphoreSlim semaphoreSlim = new SemaphoreSlim(0, 2); //all threadpool threads wait
SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 2);//only one thread has access to the resource at a time
SemaphoreSlim semaphoreSlim = new SemaphoreSlim(2, 2);//two threadpool threads can access the resource concurrently

7
Tại sao bạn không bao giờ chấp nhận câu trả lời của SVGreg?
John

Câu trả lời:


79

Có, khi số ban đầu đặt thành 0 - tất cả các chuỗi sẽ chờ trong khi bạn tăng thuộc tính "CurrentCount". Bạn có thể làm điều đó với Release () hoặc Release (Int32).

Release (...) - sẽ tăng bộ đếm semaphore

Chờ (...) - sẽ giảm nó

Bạn không thể tăng bộ đếm (thuộc tính "CurrentCount") lớn hơn số đếm tối đa mà bạn đã đặt khi khởi tạo.

Ví dụ:

SemaphoreSlim^ s = gcnew SemaphoreSlim(0,2); //s->CurrentCount = 0
s->Release(2); //s->CurrentCount = 2
...

s->Wait(); //Ok. s->CurrentCount = 1
...

s->Wait(); //Ok. s->CurrentCount = 0
...

s->Wait(); //Will be blocked until any of the threads calls Release()

1
Mã của bạn sẽ được trình bày tốt hơn trong câu trả lời hơn là dưới dạng nhận xét.
ChrisF

14
LOL - Liên minh huyền thoại có lẽ đây là lần thứ 5 tôi đạt được câu trả lời tương tự vì tài liệu của nhà xây dựng luôn khiến tôi bối rối không biết nên đặt giá trị nào. Chúc mừng
BlueStrat

70

Vì vậy, tôi thực sự bối rối về ý nghĩa của số lượng ban đầu?

Một điểm quan trọng có thể hữu ích ở đây là Waitgiảm số lượng semaphore và Releasetăng nó lên.

initialCountlà số lượng truy cập tài nguyên sẽ được phép ngay lập tức. Hay nói cách khác, đó là số lần Waitcó thể được gọi mà không bị chặn ngay sau khi semaphore được khởi tạo.

maximumCountlà số lượng cao nhất mà semaphore có thể nhận được. Đó là số lần Releasecó thể được gọi mà không đưa ra ngoại lệ giả sử initialCountsố lượng là 0. Nếu initialCountđược đặt thành cùng một giá trị maximumCountthì việc gọi Releasengay sau khi semaphore được khởi tạo sẽ đưa ra một ngoại lệ.


20
Điều này rất hữu ích! Tôi đã suy nghĩ về Semaphores trở lại, vì trong InitialCount là số tài nguyên bị CHẶN ban đầu chứ không phải số tài nguyên có sẵn ngay lập tức. Cảm ơn bạn.
Philip Tenn

5
@PhilipTenn, tôi đồng ý - tài liệu là không rõ ràng về khía cạnh này
BlueStrat

Tôi đã đồng ý, họ nên thay đổi tên biến đó hoặc cập nhật tài liệu
IronHide 21/02/17

@Sandbox bạn nên chấp nhận câu trả lời này IMO, vì nó thực sự giải thích ý nghĩa của initialCounttham số.
Michał Turczyn

8

Bạn muốn có bao nhiêu luồng để có thể truy cập tài nguyên cùng một lúc? Đặt số lượng ban đầu của bạn thành số đó. Nếu con số đó không bao giờ tăng trong suốt vòng đời của chương trình, hãy đặt số lượng tối đa của bạn thành số đó. Bằng cách đó, nếu bạn gặp lỗi lập trình trong cách bạn giải phóng tài nguyên, chương trình của bạn sẽ gặp sự cố và cho bạn biết.

(Có hai hàm tạo: một hàm chỉ nhận giá trị ban đầu và một hàm bổ sung lấy số lượng tối đa. Sử dụng cái nào thích hợp.)


1

Bằng cách này khi luồng hiện tại tạo semaphore, nó có thể yêu cầu một số tài nguyên ngay từ đầu.


Vì vậy, ý bạn là khi tôi muốn hai luồng công nhân truy cập tài nguyên, tôi nên thay đổi số lượng ban đầu?
Sandbox

Không. Đó là chuỗi hiện tại yêu cầu số lượng. Nếu bạn không muốn luồng hiện tại yêu cầu bất kỳ quyền truy cập nào bằng 0 hoặc sử dụng quá tải với một tham số.
Erno

1

Nếu bạn muốn không có luồng nào truy cập tài nguyên của bạn trong một thời gian, bạn chuyển số ban đầu là 0 và khi bạn muốn cấp quyền truy cập cho tất cả chúng ngay sau khi tạo semaphore, bạn chuyển giá trị của số ban đầu bằng số tối đa . Ví dụ:

hSemaphore = CreateSemaphoreA(NULL, 0, MAX_COUNT, NULL) ;

//Do something here
//No threads can access your resource

ReleaseSemaphore(hSemaphore, MAX_COUNT, 0) ;

//All threads can access the resource now

Như đã trích dẫn trong Tài liệu MSDN- "Một cách sử dụng khác của ReleaseSemaphore là trong quá trình khởi tạo ứng dụng. Ứng dụng có thể tạo một semaphore với số lượng ban đầu bằng 0. Điều này đặt trạng thái của semaphore thành không có ký hiệu và chặn tất cả các luồng truy cập tài nguyên được bảo vệ. Khi ứng dụng kết thúc quá trình khởi tạo, nó sử dụng ReleaseSemaphore để tăng số lượng lên giá trị lớn nhất, cho phép truy cập bình thường vào tài nguyên được bảo vệ. "


Xin lỗi, tôi đã đưa cho bạn ví dụ trong C ++ mặc dù có thể xóa nghi ngờ.
Abhineet

0

Semaphores có thể được sử dụng để bảo vệ nguồn tài nguyên . Chúng tôi sử dụng nhóm tài nguyên để sử dụng lại những thứ tốn kém để tạo - chẳng hạn như kết nối cơ sở dữ liệu.

Vì vậy, số lượng ban đầu đề cập đến số lượng tài nguyên có sẵn trong nhóm khi bắt đầu một số quy trình. Khi bạn đọc initialCountmã trong, bạn nên suy nghĩ về việc bạn đang nỗ lực trước để tạo ra nhóm tài nguyên này.

Tôi thực sự bối rối về ý nghĩa của số lượng ban đầu?

Initial count = Upfront cost

Do đó, tùy thuộc vào cấu hình sử dụng ứng dụng của bạn, giá trị này có thể có ảnh hưởng đáng kể đến hiệu suất của ứng dụng của bạn. Nó không chỉ là một số tùy ý.

Bạn nên suy nghĩ kỹ về những gì bạn tạo ra, chúng đắt như thế nào để tạo ra và số lượng bạn cần ngay lập tức. Theo nghĩa đen, bạn có thể vẽ biểu đồ giá trị tối ưu cho thông số này và có thể nên nghĩ đến việc làm cho nó có thể định cấu hình để bạn có thể điều chỉnh hiệu suất của quy trình với thời điểm mà nó đang được thực thi.


-1

Như MSDN giải thích nó trong phần Nhận xét:

Nếu số tiền ban đầu nhỏ hơn số tiền tối đa, hiệu ứng giống như khi chuỗi hiện tại đã gọi WaitOne (số tiền tối đa trừ số lần ban đầu). Nếu bạn không muốn dành bất kỳ mục nhập nào cho luồng tạo semaphore, hãy sử dụng cùng một số cho MaximumCount và InitialCount.

Vì vậy, Nếu số đếm ban đầu là 0 và tối đa là 2 thì coi như WaitOne đã được luồng chính gọi hai lần nên chúng ta đã đạt đến dung lượng (số đếm semaphore bây giờ là 0) và không có luồng nào có thể vào Semaphore. Tương tự Nếu số ban đầu là 1 và tối đa là 2 WaitOnce đã được gọi một lần và chỉ một luồng có thể vào trước khi chúng ta đạt đến dung lượng một lần nữa, v.v.

Nếu 0 được sử dụng cho số lượng ban đầu, chúng ta luôn có thể gọi Release (2) để tăng số đếm semaphore lên tối đa để cho phép số lượng luồng tối đa để lấy tài nguyên.

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.