Семафор - Какая польза от начального счета? - PullRequest
67 голосов
/ 16 января 2011

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

Чтобы создать семафор, мне нужно указать начальное и максимальное количество.MSDN заявляет, что начальное количество равно -

Начальное количество запросов на семафор, которые могут быть предоставлены одновременно.

Максимальное количество запросов на семафор, которые могут быть предоставлены одновременно.

Я могу понять, что максимальное число - это максимальное количество потоков, которые могут одновременно обращаться к ресурсу.Но какая польза от начального счета?

Если я создаю семафор с начальным счетом 0 и максимальным счетом 2, ни один из моих потоков пула не сможет получить доступ к ресурсу.Если я установлю начальный счет как 1, а максимальный счет как 2, тогда только поток пула потоков сможет получить доступ к ресурсу.Только когда я установил начальный и максимальный счет как 2, 2 потока могут получить доступ к ресурсу одновременно.Итак, я действительно запутался в значении начального счета?

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 ]

61 голосов
/ 16 января 2011

Да, когда начальное число установлено в 0 - все потоки будут ожидать, пока вы увеличиваете свойство "CurrentCount".Вы можете сделать это с помощью Release () или Release (Int32).

Release (...) - увеличит счетчик семафоров

Wait (...) - уменьшит его

Вы не можете увеличить счетчик (свойство «CurrentCount») больше максимального счетчика, установленного при инициализации.

Например:

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()
49 голосов
/ 20 февраля 2012

Итак, я действительно запутался в значении начального счета?

Здесь может помочь еще один важный момент: Wait уменьшает счетчик семафоров, а Release увеличивает его.

initialCount - количество обращений к ресурсам, которые будут разрешены немедленно. Или, другими словами, это количество раз, которое Wait можно вызвать без блокировки сразу после создания семафора.

maximumCount - это наибольшее число, которое семафор может получить. Это число раз, которое Release может быть вызвано без выдачи исключения, предполагая, что initialCount count был равен нулю. Если для initialCount установлено то же значение, что и для maximumCount, то вызов Release сразу после создания семафора вызовет исключение.

6 голосов
/ 16 января 2011

Сколько потоков вы хотите иметь доступ к ресурсу одновременно?Установите ваш начальный счет на это число.Если это число никогда не будет увеличиваться в течение срока действия программы, установите максимальное значение этого числа тоже.Таким образом, если у вас возникла программная ошибка при освобождении ресурса, ваша программа аварийно завершит работу и сообщит вам.

(Есть два конструктора: один принимает только начальное значение, а другой дополнительномаксимальное количество. Используйте в зависимости от того, что подходит.)

1 голос
/ 22 сентября 2018

Семафоры могут использоваться для защиты пула ресурсов .Мы используем пулы ресурсов для повторного использования вещей, которые дороги для создания - таких как соединения с базой данных.

Таким образом, начальное число относится к количеству доступных ресурсов в пуле в начале некоторого процесса.Когда вы читаете initialCount в коде, вы должны думать о том, сколько предварительных усилий вы вкладываете в создание этого пула ресурсов.

Меня действительно смущает значение начального счета?

Initial count = Upfront cost

Таким образом, в зависимости от профиля использованиявашего приложения, это значение может оказать существенное влияние на производительность вашего приложения.Это не просто произвольное число.

Вы должны тщательно подумать о том, что вы создаете, как дорого они создаются и сколько вам нужно сразу.Вы должны буквально уметь составлять график оптимального значения для этого параметра и, вероятно, подумать о том, чтобы сделать его настраиваемым, чтобы можно было адаптировать производительность процесса к моменту его выполнения.

1 голос
/ 20 февраля 2012

Если вы хотите, чтобы ни один поток не имел доступа к вашему ресурсу в течение некоторого времени, вы передаете начальный счет как 0, а когда вы хотите предоставить доступ ко всем из них сразу после создания семафора, вы передаете значение начального счета равным на максимальный счет. Например:

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

Как указано в Документации MSDN: «Другое использование ReleaseSemaphore - во время инициализации приложения. Приложение может создать семафор с начальным счетчиком ноль. Это устанавливает состояние семафора в состояние без сигнала и блокирует доступ всех потоков к защищенному ресурсу. Когда приложение завершает свою инициализацию, оно использует ReleaseSemaphore для увеличения счетчика до максимального значения, чтобы разрешить нормальный доступ к защищенному ресурсу. "

1 голос
/ 16 января 2011

Таким образом, когда текущий поток создает семафор, он может требовать некоторые ресурсы с самого начала.

0 голосов
/ 10 марта 2017

Как MSDN объясняет это в разделе «Примечания»:

Если initialCount меньше MaximumCount, эффект такой же, как если бы текущий поток вызывал WaitOne (MaximumCount минус initialCount) раз. Если вы не хотите резервировать какие-либо записи для потока, создающего семафор, используйте одинаковые номера для MaximumCount и initialCount.

Таким образом, если начальное количество равно 0, а максимальное равно 2, это как если бы WaitOne дважды вызывался основным потоком, поэтому мы достигли емкости (счетчик семафоров сейчас равен 0) и ни один поток не может войти в семафор. Аналогично, если начальное число равно 1, а максимальное равно 2, один раз вызывается WaitOnce, и только один поток может войти, прежде чем мы снова достигнем емкости и так далее.

Если 0 используется для начального счета, мы всегда можем вызвать Release (2), чтобы увеличить количество семафоров до максимального значения, чтобы максимальное количество потоков могло получить ресурс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...