2012-06-06 2 views
2

이 있습니까 내가 사전 클래스를 사용하여 간단한 캐시를 구현 한 :다음 코드/디자인 동시성 문제

private Dictionary<int, byte[]> cache = new Dictionary<int, byte>(); 

public void SetPicture(int id, byte[] bytes) 
{ 
    cache[id] = bytes; 
} 

public byte[] GetPicture(int id) 
{ 
    if (cache.Contains(id)) { 
     return cache[id]; 
    } 
    return null; 
} 

SetPicture은 단일 백그라운드 스레드에서 호출됩니다. 이 백그라운드 스레드는 활성 디렉터리 쿼리에서 사용자 프로필 사진을 업데이트합니다.

GetPicture는 다른 여러 스레드 (HTTP 요청을 처리하는 스레드)에서 호출됩니다.

항목이 캐시에서 절대 제거되지 않습니다.

이 코드는 안전한 스레드입니까? 또는 SetPicture에서 내부 사전에 대한 액세스를 차단해야합니까?

답변

6

아니요 안전하지 않습니다. Dictionary<,>의 내용은 이 아니기 때문에 사전에 대한 모든 액세스가 동기화되어야합니다.이 경우 라이터에 대한 독자에게는이 보장되지 않습니다. 또한 별도의 contains/get 검사는 분명한 스레드 경주입니다.

옵션 :

  • 은 1.1 스타일 Hashtable 사용 - 그래서, (키, int는, 값 형이라고 여기 하락 동기화없이 한 작가 여러 개의 동시 독자 지원 이러한
  • ConcurrentDictionary<,>
  • 이용 사용) string 같이, 기준 형 키를 사용하는 경우 Hashtable 더 매력적이다; 박스형 될 필요 ReaderWriterLockSlim
  • 사용 lock은 (가정이 아닌 사소한 쓰기) 그러나

을 동기화 (가정이 훨씬 더 많이 쓰기보다 읽기) 동기화! Hashtable 접근 방식을 사용하는 경우 을 별도로 수행하십시오. Contains/get - 인덱서 만 사용하십시오. null을 얻는다면 거기에 없었습니다. 그렇지 않으면 경쟁 조건이 있습니다.

+0

ReaderWriterLockSlim은 재미있어 보입니다. 읽기는 일반적이며 쓰기는 거의 없습니다. – GarethOwen

+0

'포함/획득'경쟁 조건과 관련하여 - 이것은 실제로 제 경우의 문제입니까? 왜냐하면 캐시에서 항목을 제거하지 않기 때문입니다 (공용 인터페이스에서는 제공하지 않음). – GarethOwen

+0

@GarethOwen 당신은 아마 괜찮을 것입니다. 그러나'TryGetValue'가 더 효율적입니다 ** 어쨌든 ** - 그럴 수도 있습니다. –

2

스레드로부터 안전하지 않습니다. ConcurrentDictionary를 사용하십시오. 또한 GetPicture 항목을 찾을 수없는 경우 뭔가 반환해야합니다.

+0

GetPicture에서 실수를 알아 줘서 고마워 - 내가 질문에 코드를 업데이 트했습니다. – GarethOwen