2016-08-26 4 views
1

ConcurrentDictionary에서 AddOrUpdate 메서드를 사용하려고했습니다.ConcurrentDictionary에서 AddOrUpdate 스레드가 안전합니까?

이 페이지의 "주의 사항"절 https://msdn.microsoft.com/en-us/library/dd287191(v=vs.110).aspx에서. 이 가 잠금에서 알 수없는 코드를 실행에서 발생할 수있는 문제를 방지하기 위해 잠금 외부에서 호출되는이 방법에 대한

그러나

"대표를 말한다. 따라서 이러한 위임에 의해 실행되는 코드는 적용되지 않습니다 작업의 원 자성. "

그래서 스레드 안전 여부는 확실하지 않습니다. 나는 그렇지 생성 나는 기능

private static void AddOrUpdate(ConcurrentDictionary<string, int> map) 
    { 
     Random r = new Random(); 
     Thread.Sleep(r.Next(10)); 
     map.AddOrUpdate(Key, 1, (key, value) => value + 1); 
    } 

    public static void TestThreadSafe(ConcurrentDictionary<string, int> map) 
    { 
     Thread[] threads = new Thread[Size]; 
     for (int i = 0; i < Size; ++i) 
     { 
      threads[i] = new Thread(() => AddOrUpdate(map)); 
     } 

     foreach (var thread in threads) 
     { 
      thread.Start(); 
     } 
    } 

아래에 쓴 1.

약 30 스레드 값을 증가시키고 병렬로 실행, 키가 발견되지 않는 경우, 값이 1, 하나의 경우가있다. 결과는 항상 300,000입니다.

위의 방법은 스레드 안전합니까? AddOrUpdate는 언제 스레드로부터 안전하지 않습니까?

+2

thread-safe인지 아닌지, 300,000 개의 스레드를 만들려고합니다. (그 전에는 최대 스레드 수를 계산할 것입니다.) (http://stackoverflow.com/a/16711010/585968)) 아마도 좋지 않습니다. 귀하의 시나리오에 대한 아이디어. 'Parallel.ForEach'는 훨씬 더 친숙합니다. – MickyD

답변

2

사용상 안전합니다. AddOrUpdate에 전달 된 대리자가 동일한 키와 기존 값에 대해 두 번 실행될 수 있으므로 부작용이있는 것은 스레드로부터 안전하지 않습니다. 예를 들어

:

private static void AddOrUpdate(ConcurrentDictionary<string, int> map) 
    { 
     Random r = new Random(); 
     Thread.Sleep(r.Next(10)); 
     map.AddOrUpdate(Key, 1, (key, value) => { Console.WriteLine(key + ": " + value); return value + 1; }); 
    } 

번 이상 동일한 키 + 값 이상을 인쇄 할 수 있습니다.

때때로 ConcurrentDictionary가 여러 스레드에서 해당 메소드를 실행 한 다음 결과 값을 가져와 잠금을 입력하여 적용하려고 할 때가 있습니다. 스레드 중 하나가 성공하고 다른 하나는 잠금을 입력하고 읽기 이후 값이 변경된 것을 확인한 다음 다시 대리인을 시도합니다.

관련 문제