경우에 쓰기 크게 능가 읽거나 (그러나 빈번) 글은 비 동시되어 A, 복사 (copy-on-write) 접근이 적절할 수있다.
아래에 표시된 구현은
- 자물쇠가없는
- 시간이 오래 걸리더라도 동시 수정 작업이 진행되는 동안에도 동시 읽기 속도가 엄청나게 빠릅니다.
- "스냅 샷"은 변경할 수 없기 때문에 잠금없는 원 자성 이 가능합니다. 즉
var snap = _list; snap[snap.Count - 1];
(물론 빈 목록을 제외하고는) 던지지 않을 것입니다. 또한 스냅 샷 의미론을 사용하여 스레드 안전 열거를 무료로 얻을 수 있습니다. 어떻게 불변성을 좋아합니다!
- 일반적으로 구현 되며 모든 데이터 구조 및 모든 유형의 수정에 적용 가능
- 죽은 간단한 , 즉 테스트, 디버그, 코드를 판독하여 확인하기 쉬운
- .Net 3.5에서 사용 가능
COW (Copy-On-Write)가 작동하려면 데이터 구조를 효과적으로 변경할 수없는 상태로 유지해야합니다 . 즉, 다른 스레드에서 사용할 수있게 한 후에는 데이터 구조 를 변경할 수 없습니다. 수정하고 싶을 때
- 구조를 복제
- 클론을 수정하다
- 수정 된 클론에 대한 참조에서 원자 적으로 교환
암호
static class CopyOnWriteSwapper
{
public static void Swap<T>(ref T obj, Func<T, T> cloner, Action<T> op)
where T : class
{
while (true)
{
var objBefore = Volatile.Read(ref obj);
var newObj = cloner(objBefore);
op(newObj);
if (Interlocked.CompareExchange(ref obj, newObj, objBefore) == objBefore)
return;
}
}
}
용법
CopyOnWriteSwapper.Swap(ref _myList,
orig => new List<string>(orig),
clone => clone.Add("asdf"));
더 많은 성능이 필요한 경우 메소드를 강화하는 데 도움이됩니다. 예를 들어 원하는 모든 수정 유형 (추가, 제거 등)에 대해 하나의 메소드를 작성하고 함수 포인터 cloner
및 하드 코드를 작성하십시오 op
.
NB # 1 아무도 불변의 데이터 구조를 수정하지 않도록하는 것은 귀하의 책임입니다. 이를 막기 위해 일반적인 구현 에서는 할 수있는 일은 없지만 List<T>
,를 전문화 할 때 List.AsReadOnly ()를 사용하여 수정을 막을 수 있습니다.
NB # 2 목록의 값에주의하십시오. 위의 copy on write 접근법은 목록 멤버쉽 만 보호하지만 문자열을 넣지 않고 다른 가변 객체를 넣을 경우 스레드 안전을 관리해야합니다 (예 : 잠금). 그러나 이것은이 솔루션과 직교하며 변경 가능한 값의 잠금은 문제없이 쉽게 사용할 수 있습니다. 당신은 그것을 알고 있어야합니다.
NB # 3 데이터 구조가 거대하고 자주 수정하는 경우, 복사 중 복사 방식은 메모리 소비 및 관련 복사 비용과 관련하여 금지 될 수 있습니다. 이 경우 대신 MS의 Immutable Collection 을 사용할 수 있습니다 .