2009-08-06 3 views
2

나는 다중 스레드 C# 응용 프로그램을 가지고 있습니다. 동시에 N 개의 다른 스레드에서 액세스하는 사전이 하나 있습니다. 호출의 99 %는 스레드 A에서 온 것이고 나머지는 B, C, ...에서 나온 것입니다.C# 스레딩 성능, 한 스레드 99 % 시간

지금 당장은 각 액세스에서 사전을 잠글 것입니다. 하지만 시간 낭비라고하는 99 %의 시간이 스레드 A에 이미 잠겨 있기 때문에 낭비가됩니다.

이 작업을 수행하는보다 효율적인 방법은 무엇입니까?

어떤 종류의 .Begin과 .End 호출은 B, C, ... 스레드에 필요할 수 있습니다. 그러면 스레드 A는 각 호출에서 하나의 비트를 검사하여 다른 스레드가 사용하고 있는지 확인해야합니다. 사전. 누구든지 스레드 안전 방식으로 구현 된 이와 같은 코드 샘플을 가지고 있습니까?

+0

이 참조 디자인 http://stackoverflow.com/questions/157933/whats-the-best-way-of-implementing-a에 의해 안전 스레드의 시도 -thread-safe-dictionary-in-net –

답변

4

프로필러 데이터를 신중하게 검사해야합니다.

실제 경합이 발생하지 않는 한 모니터와 RWLSlim은 실제로 "하드 고정"되지 않습니다 (OS 기본형으로 드롭 다운). 다른 모든 경우에는 Interlocked가 사용되며 캐시 플러시와 별도로 상대적으로 최소한의 영향을 미칩니다.

성능면에서 RWLockSlim은 비교적 비싸고 모니터를 입력하는 것보다 약간 비쌉니다. 그것의 미덕은 다중 독자와 한 작가를 허용하는 것입니다.

하드락이 나타나면 실제로 논쟁을 벌이게됩니다.이 경우 99 %/1 %/1 %/1 %/...의 비율은 실제로 현실을 반영하지 않습니다.

이전의 포스터에서 언급했듯이, 대부분의 경우 글을 쓰거나 대량으로 읽는 경우가 많습니다. 그렇지 않으면 시스템의 일관성이 다소 힘들어집니다. 이 경우 RWlockSlim은 불필요한 경합을 제거해야합니다.

하단 : 모든 것은 당신이하려는 일에 달려 있습니다 -이 사전이 무엇이고 어떻게 접근하고 있는지에 따라 다릅니다. 때로는 너무 많은 것을 차지하지 않도록 자물쇠를 넓히는 것이 합리적입니다. 그리고 아주 드물게 "진짜"자물쇠를 치기 전에 Interlocked와 같은 자물쇠가없는 스타일의 프리미티브로 놀고 싶을 수도 있습니다.

아마도 시나리오에 대해 자세히 이야기 해 주시면 더 잘 도와 드릴 수 있습니다.

2

어떻게 잠금을 수행합니까? 독서를 위해 당신은 또한 당신이 또한 새롭게하고있는 것처럼 동일한 "어려운"방법으로 다른 스레드를 잠글 필요가 없습니다. 어느 쪽이든 당신은 좀 더 느슨한 읽기 작업을 할 수 있습니다. 나는 (당신이 이미 그것을 사용하지 않는 경우)에 ReaderWriterLockSlim에보고 제안 :를 업데이트 할 때 다른 스레드에서 액세스를 차단하면서는 여러 스레드가 "동시에"사전에서 읽을 수

class DictionaryHolder 
{ 
    private IDictionary<int, string> _data = new Dictionary<int, string>(); 
    private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); 
    public void Update(int key, string value) 
    { 
     _lock.EnterWriteLock();    
     try 
     { 
      _data[key] = value; 
     } 
     finally 
     { 
      _lock.ExitWriteLock(); 
     } 
    } 

    public string GetValue(int key) 
    { 
     _lock.EnterReadLock(); 
     try 
     { 
      if (_data.ContainsKey(key)) 
      { 
       return _data[key]; 
     } 
     finally 
     { 
      _lock.ExitReadLock(); 
     } 
    } 
} 

.

+0

감사합니다. ReaderWriterLockSlim에 대해 생각하고있었습니다. "_lock.EnterReadLock()"의 perf가 "Monitor.Enter"와 어떻게 비교되는지 알고 싶습니다. 나는 전에 그것을 사용한 적이 없다. –

+0

잠금을 획득하는 성능에 대해서는 언급 할 수 없지만, '_lock.EnterReadLock'의 장점은 리더 잠금을 원하는 다른 스레드를 잠그지 않는 것입니다. 다른 스레드가 사전에 접근하는 것을 막을 잠금 장치가 있다는 것은 업데이트 작업 ('_lock.EnterReadLock'에 의해 보호됨)을 통해서만 가능합니다. –

2

프로파일 러에서 Monitor.Enter 및 회사에서 많은 시간을 보내고 있다고 프로파일 러가 알리는 경우가 아니면 걱정하지 않아도됩니다. 일반적으로 비경쟁 잠금 또는 이미 보유한 잠금을 획득하는 것은 매우 빠른 작업이므로 당신이 제안하는 비트 체크와 성능면에서 비슷합니다. 잠금 조작은 경합으로 인해 블록되어야 할 때 일반적으로 느립니다.

+0

감사합니다. 안타깝게도 ANTS 프로파일 러에 따르면 잠금 호출은 내가 기능에서 소비하는 시간의 상당 부분을 차지합니다. –

1

ReaderWriterLockSlim은 많은 독자와 작가가있는 경우 도움이됩니다. 그러나 ReaderWriterLockSlim의 개별 작동 성능은 A Performance Comparison of ReaderWriterLockSlim with ReaderWriterLock 링크에 따라 Monitor보다 작아 보입니다.

시도해 볼 수있는 옵션 중 하나는 이벤트 개체와 함께 연동 작업을 통해 스레드를 동기화하는 것입니다. 그러나 다시 한번이 접근 방식의 성능을 측정해야합니다.

0

은 .NET에서 System.Collections.Concurrent.ConcurrentDictionary를 사용하여 4.0

그것은

+0

.NET에서 좋은 옵션입니다. 4. 구현 방법을 알고 있습니까? 나는 어떻게 그것이 일반 사전에 대한 모든 액세스를 잠그는 것과 비교하여 어떻게 수행하는지 궁금해합니다. –

+1

System.Collections.Concurrent 멤버는 기본 제공 스레드로부터 안전합니다. 특별한 일은 없습니다. 예를 들어, 여러 개의 스레드가있는 동시 대기열을 사용하고 아무런 고려없이 '대기열에 넣기'또는 '대기열에서 빼기'를 호출하십시오. 세부 사항을 원한다면 Reflector를 원하는 라이브러리에 사용하여 구현하십시오. 내 경험 에선 속도가 좋다. – Xaqron