2009-12-21 5 views
0

오늘 내 문제를 해결할 here nice answer이 있습니다. 불행히도, 나는 잠그는 법을 잊어 버렸다.잠그기, 질문하기

문제는 간단합니다. 서버에서 연결된 각 클라이언트는 최대 클라이언트 인 1에서 500까지 고유 한 ID (재사용 가능)를 갖게됩니다.

대답은 qeue를 만들고 대기중인 요소를 새 연결에 사용하고 릴리스 될 때 다시 반환하는 것이 었습니다.

내가 제대로 이해하는지 모르겠다. 또한 500 요소 (ints)로 qeue를 초기화하고 하나씩 가져 와서 한 번 릴리스 된 상태로 되돌려 야합니까?

그렇다면 자물쇠를 사용했기 때문에 내 질문은 주로 성능을 목표로했습니다.

답변

1

는 병렬 확장을 사용할 수 있다면 당신이 그렇고 허브 셔터

에 의해 this article에 자신을 구현하는 방법을 찾을 수없는 경우 ConcurrentQueue

에 대한 이동합니다 존 소총의 대답은 말하고있다 당신은 unqueue하려고 시도하고 빈 경우 생성하고 사용하려고합니다. ID로 끝나면 큐에 넣기 만하면됩니다. 500 개의 ID에 대한 참조는 없습니다. 500 개의 id로 제한해야하는 경우 500 개의 id로 큐를 초기화 한 다음 새로운 큐를 생성하는 대신 큐가 비어있을 때 BLOCK을 초기화해야합니다. 그 때문에 consumer/producer pattern이 더 적합합니다.

+0

간단한 잠금만으로 충분합니다. – Thomas

+0

+1 사소한 수정 ... BLOCKING은 더 이상 사용할 수있는 연결이 없을 때 수행 할 작업의 응용 프로그램 문제에 대한 유일한 해결책입니다. 시스템 및 컨텍스트에 따라 오류 코드를 반환하거나 대신 예외를 throw 할 수 있습니다 (또는 관련된 다른 오류 처리 패러다임). 그렇지 않으면 훌륭한 대답. – James

0

나는 당신이하고 싶은 것을 이해하지 못합니다.

사용한 숫자에 대한 해시 테이블을 채울 수 있습니다.

그리고 다양한 변수에 응용 프로그램을 저장하고 해당 리소스에 액세스하는 동안 Application.Lock 및 Application.Unlock 메서드를 사용할 수 있습니다.

0

이와 비슷한?

/// <summary> 
/// Thread safe queue of client ids 
/// </summary> 
internal class SlotQueue 
{ 
    private readonly AutoResetEvent _event = new AutoResetEvent(false); 
    private readonly Queue<int> _items = new Queue<int>(); 
    private int _waitCount; 

    /// <summary> 
    /// Initializes a new instance of the <see cref="SlotQueue"/> class. 
    /// </summary> 
    /// <param name="itemCount">The item count.</param> 
    public SlotQueue(int itemCount) 
    { 
     // Create queue items 
     for (int i = 0; i < itemCount; ++i) 
      _items.Enqueue(i); 
    } 

    /// <summary> 
    /// Gets number of clients waiting in the queue. 
    /// </summary> 
    public int QueueSize 
    { 
     get { return _waitCount; } 
    } 

    /// <summary> 
    /// 
    /// </summary> 
    /// <param name="waitTime">Number of milliseconds to wait for an id</param> 
    /// <returns></returns> 
    public int Deqeue(int waitTime) 
    { 
     // Thread safe check if we got any free items 
     lock (_items) 
     { 
      if (_items.Count > 0) 
       return _items.Dequeue(); 
     } 

     // Number of waiting clients. 
     Interlocked.Increment(ref _waitCount); 

     // wait for an item to get enqueued 
     // false = timeout 
     bool res = _event.WaitOne(waitTime); 
     if (!res) 
     { 
      Interlocked.Decrement(ref _waitCount); 
      return -1; 
     } 

     // try to fetch queued item 
     lock (_items) 
     { 
      if (_items.Count > 0) 
      { 
       Interlocked.Decrement(ref _waitCount); 
       return _items.Dequeue(); 
      } 
     } 

     // another thread got the last item between waitOne and the lock. 
     Interlocked.Decrement(ref _waitCount); 
     return -1; 
    } 

    /// <summary> 
    /// Enqueue a client ID 
    /// </summary> 
    /// <param name="id">Id to enqueue</param> 
    public void Enqueue(int id) 
    { 
     lock (_items) 
     { 
      _items.Enqueue(id); 
      if (_waitCount > 0) 
       _event.Set(); 
     } 
    } 
}