세마포어-초기 카운트의 사용은 무엇입니까?


91

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
SVGreg의 대답을 어떻게 받아들이지 않았습니까?
John

답변:


79

예, 초기 숫자가 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()

1
귀하의 코드는 주석이 아닌 답변에 더 잘 표시됩니다.
ChrisF

14
LOL 생성자의 문서가 항상 어떤 값을 설정할지 혼동하기 때문에이 같은 대답에 도달 한 것은 아마도 5 번째 일 것입니다. 건배
BlueStrat 16.10.11

70

그래서, 나는 초기 카운트의 중요성에 대해 정말로 혼란 스럽습니까?

여기서 도움이 될 수있는 한 가지 중요한 점 Wait은 세마포어 수를 Release줄이고 증가시키는 것입니다.

initialCount즉시 허용되는 리소스 액세스 수입니다. 즉, Wait세마포어가 인스턴스화 된 직후 차단하지 않고 호출 할 수있는 횟수입니다 .

maximumCount세마포어가 얻을 수있는 최대 개수입니다. 이것은 배의 개수 Release가정 던지고 예외없이 호출 될 수있는 initialCount수는 0이었다. 경우 initialCount와 같은 값으로 설정 maximumCount한 후 호출 Release세마포어는 예외가 발생합니다 인스턴스화 직후.


20
이것은 매우 도움이됩니다! 나는 initialCount가 즉시 사용 가능한 리소스 수가 아니라 초기 BLOCKED 리소스의 수이므로 Semaphores에 대해 거꾸로 생각했습니다. 감사합니다.
Philip Tenn 2014 년

5
@PhilipTenn, 동의합니다-문서는이 점에 대해 명확하지 않습니다
BlueStrat

나는 그들이 문서를 해당 변수의 이름을 변경하거나 업데이트해야합니다 동의
아이언 하이드

@Sandbox는 initialCount매개 변수 의 의미를 실제로 설명 하므로이 답변 IMO를 수락해야합니다 .
Michał Turczyn

8

한 번에 리소스에 액세스 할 수있는 스레드 수를 원하십니까? 초기 카운트를 그 숫자로 설정하십시오. 이 숫자가 프로그램 수명 동안 절대 증가하지 않으면 최대 개수도 해당 숫자로 설정하십시오. 이렇게하면 리소스를 해제하는 방법에 프로그래밍 오류가있는 경우 프로그램이 충돌하여 알려줍니다.

(두 개의 생성자가 있습니다. 하나는 초기 값 만 취하는 것이고 다른 하나는 추가적으로 최대 개수를 취하는 것입니다. 둘 중 적절한 것을 사용하십시오.)


1

이런 식으로 현재 스레드가 세마포어를 만들 때 시작부터 일부 리소스를 요청할 수 있습니다.


그렇다면 두 작업자 스레드가 리소스에 액세스하도록하려면 초기 개수를 변경해야한다는 의미입니까?
Sandbox

아니요. 카운트를 요구하는 것은 현재 스레드입니다. 현재 스레드가 액세스를 요청하지 않도록하려면 0을 전달하거나 하나의 매개 변수와 함께 오버로드를 사용하십시오.
Erno 2011 년

1

스레드가 일정 시간 동안 리소스에 액세스하지 않도록하려면 초기 카운트를 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의 또 다른 사용은 응용 프로그램의 초기화 중에 있습니다. 응용 프로그램은 초기 개수가 0 인 세마포어를 만들 수 있습니다. 이렇게하면 세마포어의 상태가 신호 없음으로 설정되고 모든 스레드가 보호 된 리소스에 액세스하는 것을 차단합니다. 초기화를 마치면 ReleaseSemaphore를 사용하여 개수를 최대 값으로 늘리고 보호 된 리소스에 대한 정상적인 액세스를 허용합니다. "


미안합니다. 의심을 없앨 수 있지만 C ++로 예제를 제공했습니다.
Abhineet 2012

0

세마포어는 리소스 풀을 보호하는 데 사용할 수 있습니다 . 리소스 풀을 사용 하여 데이터베이스 연결과 같이 생성 비용많이 드는 것을 재사용 합니다.

따라서 초기 수는 일부 프로세스 시작시 풀에서 사용 가능한 리소스 수를 나타냅니다. 인 initialCount코드 를 읽을 때이 리소스 풀을 만드는 데 얼마나 많은 노력을 기울이고 있는지 생각해야합니다.

나는 초기 카운트의 중요성에 대해 정말로 혼란 스럽습니까?

Initial count = Upfront cost

따라서 애플리케이션의 사용 프로필에 따라이 값은 애플리케이션 성능에 큰 영향을 미칠 수 있습니다. 단지 임의의 숫자가 아닙니다.

무엇을 만들 었는지, 만드는 데 얼마나 많은 비용이 드는지, 즉시 필요한만큼을 신중하게 생각해야합니다. 말 그대로이 매개 변수에 대한 최적의 값을 그래프로 표시 할 수 있어야하며 프로세스의 성능을 실행되는 시간에 맞게 조정할 수 있도록 구성 가능하게 만드는 것에 대해 생각해야합니다.


-1

MSDN 이 설명 섹션에서 설명 했듯이 :

initialCount가 maximumCount보다 작 으면 현재 스레드가 WaitOne (maximumCount 빼기 initialCount)을 호출 한 것과 효과가 동일합니다. 세마포어를 생성하는 스레드에 대한 항목을 예약하지 않으려면 maximumCount 및 initialCount에 동일한 수를 사용하십시오.

따라서 초기 카운트가 0이고 max가 2이면 메인 스레드가 WaitOne을 두 번 호출하여 용량에 도달하고 (이제 세마포어 카운트가 0 임) 스레드가 Semaphore에 들어갈 수 없습니다. 유사하게 초기 카운트가 1이고 최대가 2이면 WaitOnce가 한 번 호출되고 다시 용량에 도달하기 전에 하나의 스레드 만 들어갈 수 있습니다.

초기 카운트에 0이 사용되면 리소스를 획득하기위한 최대 스레드 수를 허용하기 위해 세마포어 카운트를 최대로 늘리기 위해 항상 Release (2)를 호출 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.