2015-02-05 2 views
-1

IncrementModelClientReOrderCount를 실행할 때 교착 상태가 발생하지만 IncrementModelClientReOrderCountLOCK을 실행하면 문제가 사라집니다.왜이 TryGetValue/TryUpdate가 ConcurrentDictionary에서 교착 상태에 빠질 수 있습니까?

차이점은 lock() 문입니다.

나는 ConcurrentDictionary를 사용하면 교착 상태가 발생하지 않는다고 가정했다.

내가 잘못 아마도 ConcurrentDictionary을 사용하고 있습니다 :

public ConcurrentDictionary<Connection, ModelClient> ModelClients = new ConcurrentDictionary<Connection, ModelClient>(); 



    public bool IncrementModelClientReOrderCount(Connection mc) 
    { 
      ModelClient curValue; 
      while (ModelClients.TryGetValue(mc, out curValue)) 
      { 
       ModelClient curValue2 = curValue.Clone() as ModelClient; 
       curValue2.reOrderCount++; 
       curValue2.DSP.seen = false; 
       if (ModelClients.TryUpdate(mc, curValue2, curValue)) 
        return true; 

      } 
      return false; 
    } 


    public bool IncrementModelClientReOrderCountLOCK(Connection mc) 
    { 
     lock (ModelClients) 
     { 

      ModelClient curValue; 
      while (ModelClients.TryGetValue(mc, out curValue)) 
      { 
       ModelClient curValue2 = curValue.Clone() as ModelClient; 
       curValue2.reOrderCount++; 
       curValue2.DSP.seen = false; 
       if (ModelClients.TryUpdate(mc, curValue2, curValue)) 
        return true; 
      } 
      return false; 
     } 

    } 


public class ModelClient : ICloneable 
    { 
     public string Symbol; 
     public int Amount; 
     public double Price; 

     public ModelClient(string Symbol, int Amount, double Price) 
     { 
      this.Symbol = Symbol; 
      this.Amount = Amount; 
      this.Price = Price; 
     } 

     public object Clone() { return this.MemberwiseClone(); } 
    } 
+2

왜 교착 상태가 'ConcurrentDictionary'에 의해 발생한다고 가정합니까? –

+0

@YuvalItzchakov OK. 나는 그것이 다른 것일지도 모르지만 그 방법에서 발생합니다. 범인이 될만한 다른 것을 본 적이 있습니까? – ManInMoon

+0

'복제 '는 맞춤 구현입니까? –

답변

0

A "스레드 안전"컬렉션 스레드 안전 자신에게있다 -하지 컬렉션이 작성 될 때 존재하지 않는 다른 모든 코드. ConncurrentDictionary도 잠금 해제가되어 있지 않습니다. 즉, 입니다. 따라서 일부 메소드에 대한 호출을 차단할 가능성이 있습니다. (예를 들어, 동시에 진행하는 동안 두 스레드는 모두 동시에 ConcurrentDictionary에서 차단 메소드를 호출 함)

잠금의 특성은 두 개의 코드가 동시에 실행되어 손상 될 수 있으므로 상태 - 코드에 항상 두 개 이상의 블록이 있으므로 lock을 사용하므로 두 블록의 실행이 겹치고 교착 상태가 발생할 수 있습니다.

스레드 안전 수집은 다중 스레드에서 사용할 수 있다는 것을 의미하며 스레드 자체의 상태를 손상시키지 않습니다 (액세스 할 수없고 자신을 보호 할 수없는 상태). 스레드 세이프 컬렉션을 사용한다고해서 자동으로 모든 코드가 스레드로부터 안전 해지는 것은 아니며, 잠재적 인 교착 상태를 이해하고 자신의 스레드 안전 프리미티브를 사용하여 보상 할 필요도 없습니다.

정확히 어떻게 교착 상태에 빠졌는지 (또는 실제로 라이브 록인지) 알 수있는 충분한 코드를 제공하지 못했습니다. 다른 스레드가 동일한 curValue으로 TryUpdate라고한다면, TryUpdate을 차단할 수 있습니다, 나는 TryUpdate false를 반환 기대하고 코드 당신이 사이에 불변이 나타납니다 (즉, 잠재적 인 라이브 락에게 모든 것을 다시

을 시도 할 것 을 통해 값을 얻고 TryUpdate으로 업데이트하면이 불변 값이 코드에 고유하므로 사용자가이를 지켜야합니다. lock은 좋은 출발이지만, lock이 최고라고 받아들이 기 전에 더 잘 이해해야합니다. 솔루션입니다.

관련 문제