2010-12-15 4 views
2

lock 문을 사용하여 C#에서 간단한 잠금을 사용하고 있습니다. 얼마나 많은 다른 스레드가 객체를 잠그기를 기다리고 있는지 판단 할 수있는 방법이 있습니까? 기본적으로 잠금을 기다리는 스레드 수를 5로 제한하고 싶습니다. 여섯 번째 스레드가 잠금을 가져와야하는 경우 내 코드에서 예외가 발생합니다.C#에서 잠글 대기 스레드 수를 확인할 수있는 방법이 있습니까?

+6

이것은 귀찮은 솔루션의 후반부처럼 들립니다. 당신이 해결하려고하는 실제 문제는 무엇입니까? –

+0

설명하기가 어렵지만 제 3 자 웹 서비스를 감싸는 객체를 가지고 있습니다. 트릭은 제 3 자 서비스에 대한 호출이 동기화되어야하므로 래퍼 객체를 잠그는 것입니다. 웹 사이트 환경에서 래퍼 객체를 사용하므로 여러 스레드가 동시에이를 사용할 수 있습니다. 대기중인 스레드 대기열을 5 개로 제한하려는 이유는 DoS 연결을 만드는 것이 얼마나 쉬운지를 약간 염려하기 때문입니다. 타사 웹 서비스는 매우 느리므로 누군가가 쉽게 요청을 보낼 수 있으며 차단 된 스레드가 100 개가 있습니다. –

+1

@Ben : 당신이 제한해야하는 리소스가 시스템의 쓰레드 수 *가 아닌, * 얼마나 많은 사람들이 잠금을 기다릴 수 있는지와 같은 것 같습니다. 요청 당 하나의 스레드를 만들지 마십시오. 프로세서 당 하나의 스레드를 만들고, 프로세서가 부족한 경우 스레드가 해제 될 때까지 클라이언트를 대기 시키십시오. –

답변

3

이 작업은 Semaphore 클래스를 통해 쉽게 수행 할 수 있습니다. 그것은 당신을위한 계산을 할 것입니다. 아래의 코드에서 리소스를 기다리는 스레드의 수를 non-blocking으로 확인하기 위해 세마포어를 사용하고 일반 old lock을 사용하여 실제로 해당 리소스에 대한 액세스를 직렬화합니다. 자원을 대기 중의 thread가 5 개 이상있는 경우, 예외가 Throw됩니다.

public class YourResourceExecutor 
{ 
    private Semaphore m_Semaphore = new Semaphore(5, 5); 

    public void Execute() 
    { 
    bool acquired = false; 
    try 
    { 
     acquired = m_Semaphore.WaitOne(0); 
     if (!acquired) 
     { 
     throw new InvalidOperationException(); 
     } 
     lock (m_Semaphore) 
     { 
     // Use the resource here. 
     } 
    } 
    finally 
    { 
     if (acquired) m_Semaphore.Release(); 
    } 
    } 
} 

이 패턴에는 주목할만한 변형이 있습니다. 메서드 이름을 TryExecute으로 변경하고 예외를 throw하는 대신 bool을 반환 할 수 있습니다. 그것은 전적으로 당신에게 달렸습니다.

잠금 식에 사용 된 개체가 이 아니고 잠금 대상이임을 기억하십시오. 이것은 단순히 동기화 된 코드 블록의 식별자 역할을합니다. 동일한 객체을 사용하여 잠금을 획득하는 코드 블록은 효과적으로 직렬화됩니다. lock 표현식에 사용 된 객체가 아니라 "잠긴"코드 블록입니다.

+0

나는 이것을 이해한다고 생각하지만 m_Semaphore가 lock()을 사용하여 잠겨 졌을 때 다른 스레드가 세마포 잠금을 획득 할 수 있습니까? lock()이 별도의 객체에 있어야하는지 궁금합니다. –

+0

@Ben : 예, 확실히 '잠금'을 위해 별도의 객체를 사용할 수 있습니다. 방금 별도의 객체를 만드는 것과는 달리 이미 존재했던 객체를 사용하기로했습니다. '세마포어 '에'잠금'을 사용하면 결코 세마포어의 동작에 영향을 미치지 않습니다. –

+0

@Brian, 저는이 점을 처음 접했지만 lock()을 통해 객체에 대한 잠금 기능을 사용하면 다른 스레드가 어떤 방식 으로든 객체에 액세스 할 수 없다고 생각했습니다. –

1

lock 문 앞에 증가하는 간단한 공유 카운터 (정수)를 사용할 수 있습니다. 값이 5와 같으면 스레드가 lock 문을 피하십시오. 그러나 문제는 증가 작업이 원자적임을 보장하기 위해 카운터를 잠글 필요가 있다는 것입니다.

+0

을 참조하십시오. Interlocked.Increment를 할 수 있습니다. –

+0

콘래드의 제안에 +1; 아마도 이것을 구현하는 가장 간단한 방법 일 것입니다. – KeithS

1

아니요, lock()Monitor class을 사용하며 대기중인 스레드의 수를 확인할 수있는 구성원이 없습니다.

시간 제한을 지정할 수 있습니다.

솔직히 말해 큐가 가득 차면 Exception을 throw하여 나쁜 생각처럼 들립니다.

2

lock 문은 Monitor.EnterMonitor.Exit의 바로 가기입니다. 나는 기다리는 물건의 수를 얻을 기회가 있다고 생각하지 않는다.

관련 문제