동시 가방 대 목록
목록(내 유형)만 사용하는 것에 비해 동시에 가방(내 유형)을 사용하는 것의 이점은 무엇입니까?CB의 MSDN 페이지에는 다음과 같이 나와 있습니다.
ConcurrentBag(Of T)는 동일한 스레드가 백에 저장된 데이터를 생성하고 소비하는 시나리오에 최적화된 스레드 세이프 백 구현입니다.
그렇다면 이점은 무엇일까요?Concurrency 네임스페이스에서 다른 컬렉션 유형의 이점을 이해할 수 있지만, 이는 저를 어리둥절하게 했습니다.
내부적으로 ConcurrentBag는 여러 개의 서로 다른 목록(각 쓰기 스레드에 하나씩)을 사용하여 구현됩니다.
당신이 인용한 문장은 가방에서 읽을 때 해당 스레드에 대해 작성된 목록의 우선순위를 지정한다는 것을 의미합니다.즉, 다른 스레드의 목록에서 경합이 발생하기 전에 먼저 해당 스레드의 목록을 확인합니다.
이렇게 하면 여러 스레드가 읽고 쓸 때 잠금 경합을 최소화할 수 있습니다.읽기 스레드에 목록이 없거나 목록이 비어 있으면 다른 스레드에 할당된 목록을 잠가야 합니다.그러나 여러 개의 스레드가 모두 자신의 목록에서 읽고 쓰는 경우 잠금 경합이 발생하지 않습니다.
여기서 가장 큰 장점은ConcurrentBag<T>
여러 스레드에서 액세스하는 것이 안전합니다.LisT<T>
아닙니다.스레드 안전 액세스가 시나리오에 중요한 경우 다음과 같은 유형이 있습니다.ConcurrentBag<T>
보다 당신에게 유리할 수 있습니다.List<T>
수동 잠금이 질문에 대답하기 전에 귀하의 시나리오에 대해 좀 더 알아야 합니다.
또한.List<T>
주문형 컬렉션입니다.ConcurrentBag<T>
아닙니다.
TLDR: 로컬 잠금이 더 빠르지만 차이는 무시할 수 있습니다(또는 테스트를 설정했습니다).
성능 분석:
private static IEnumerable<string> UseConcurrentBag(int count)
{
Func<string> getString = () => "42";
var list = new ConcurrentBag<string>();
Parallel.For(0, count, o => list.Add(getString()));
return list;
}
private static IEnumerable<string> UseLocalLock(int count)
{
Func<string> getString = () => "42";
var resultCollection = new List<string>();
object localLockObject = new object();
Parallel.For(0, count, () => new List<string>(), (word, state, localList) =>
{
localList.Add(getString());
return localList;
},
(finalResult) => { lock (localLockObject) resultCollection.AddRange(finalResult); }
);
return resultCollection;
}
private static void Test()
{
var s = string.Empty;
var start1 = DateTime.Now;
var list = UseConcurrentBag(5000000);
if (list != null)
{
var end1 = DateTime.Now;
s += " 1: " + end1.Subtract(start1);
}
var start2 = DateTime.Now;
var list1 = UseLocalLock(5000000);
if (list1 != null)
{
var end2 = DateTime.Now;
s += " 2: " + end2.Subtract(start2);
}
if (!s.Contains("sdfsd"))
{
}
}
5M 레코드를 사용하여 ConcurrentBag를 3회 실행하면 오류가 발생할 수
" 1: 00:00:00.4550455 2: 00:00:00.4090409"
" 1: 00:00:00.4190419 2: 00:00:00.4730473"
" 1: 00:00:00.4780478 2: 00:00:00.3870387"
동시 실행 3회 실행(5M 레코드의 로컬 잠금 대비):
" 1: 00:00:00.5070507 2: 00:00:00.3660366"
" 1: 00:00:00.4470447 2: 00:00:00.2470247"
" 1: 00:00:00.4420442 2: 00:00:00.2430243"
5,000만 개의 레코드로
" 1: 00:00:04.7354735 2: 00:00:04.7554755"
" 1: 00:00:04.2094209 2: 00:00:03.2413241"
로컬 잠금이 조금 더 빠릅니다.
업데이트: (Xeon X5650 @ 2.67GHz 64비트 Win76 코어) 'local lock'이 훨씬 더 나은 성능을 발휘하는 것 같습니다.
5천만 개의 레코드로.
1: 00:00:09.7739773 2: 00:00:06.8076807
1: 00:00:08.8858885 2: 00:00:04.6184618
1: 00:00:12.5532552 2: 00:00:06.4866486
다른 동시 수집과 달리ConcurrentBag<T>
단일 프로세서 사용에 최적화되어 있습니다.
와는과 다르게 .List<T>
,ConcurrentBag<T>
여러 스레드에서 동시에 사용할 수 있습니다.
"여러 스레드가 컨테이너에 액세스하고 각 스레드가 데이터를 생성 및/또는 소비할 수 있는" 경우, 이는 분명히 병렬 시나리오를 위한 것입니다.
언급URL : https://stackoverflow.com/questions/2950955/concurrentbagmytype-vs-listmytype
'programing' 카테고리의 다른 글
Oracle SQL - NULL 값이 있는 max() (0) | 2023.06.17 |
---|---|
SQL: 사용 가능한 모든 테이블에서 모든 데이터 삭제 (0) | 2023.06.17 |
목록 모음에서 메서드 선택 (0) | 2023.06.17 |
테이블에 명명된 검사 제약 조건 추가 (0) | 2023.06.12 |
개인 클래스 메소드를 만드는 방법은 무엇입니까? (0) | 2023.06.12 |