스레드로부터 안전한 컬렉션Thread-Safe Collections

.NET Framework 4에서는 네임스페이스는 스레드로부터 안전하면서 확장 가능한 몇 가지 컬렉션 클래스를 포함하는 System.Collections.Concurrent 네임스페이스를 도입합니다.The .NET Framework 4 introduces the System.Collections.Concurrent namespace, which includes several collection classes that are both thread-safe and scalable. 여러 스레드는 사용자 코드에서 추가로 동기화할 필요없이 이러한 컬렉션으로부터 안전하고 효율적으로 항목을 추가하거나 제거할 수 있습니다.Multiple threads can safely and efficiently add or remove items from these collections, without requiring additional synchronization in user code. 새 코드를 작성하는 경우 여러 스레드가 컬렉션에 동시에 작성될 때마다 동시 컬렉션 클래스를 사용합니다.When you write new code, use the concurrent collection classes whenever multiple threads will write to the collection concurrently. 공유 컬렉션에서 읽기만 하는 경우에 System.Collections.Generic 네임스페이스에서 클래스를 사용할 수 있습니다.If you are only reading from a shared collection, then you can use the classes in the System.Collections.Generic namespace. .NET Framework 1.1 또는 이전 런타임을 대상으로 해야 하는 경우가 아니면 1.0 컬렉션 클래스를 사용하지 않는 것이 좋습니다.We recommend that you do not use 1.0 collection classes unless you are required to target the .NET Framework 1.1 or earlier runtime.

.NET Framework 1.0 및 2.0 컬렉션에서 스레드 동기화Thread Synchronization in the .NET Framework 1.0 and 2.0 Collections

.NET Framework 1.0에 도입된 컬렉션은 System.Collections 네임스페이스에 있습니다.The collections introduced in the .NET Framework 1.0 are found in the System.Collections namespace. 일반적으로 사용되는 ArrayListHashtable을 포함하는 이러한 컬렉션은 컬렉션 주변에서 스레드로부터 안전한 래퍼를 반환하는 Synchronized 속성을 통해 어느 정도 스레드로부터의 안전성을 제공합니다.These collections, which include the commonly used ArrayList and Hashtable, provide some thread-safety through the Synchronized property, which returns a thread-safe wrapper around the collection. 래퍼는 모든 추가 또는 제거 작업에서 전체 컬렉션을 잠그는 방식으로 작동합니다.The wrapper works by locking the entire collection on every add or remove operation. 따라서 컬렉션에 액세스하려고 하는 각 스레드는 잠금을 사용하기 위해 차례를 기다려야 합니다.Therefore, each thread that is attempting to access the collection must wait for its turn to take the one lock. 이것은 확장할 수 없고 큰 컬렉션에 상당한 성능 저하가 발생할 수 있습니다.This is not scalable and can cause significant performance degradation for large collections. 또한 디자인은 경합 조건에서 완전히 보호되지 않습니다.Also, the design is not completely protected from race conditions. 자세한 내용은 제네릭 컬렉션에서의 동기화를 참조하세요.For more information, see Synchronization in Generic Collections.

.NET Framework 2.0에 도입된 컬렉션 클래스는 System.Collections.Generic 네임스페이스에 있습니다.The collection classes introduced in the .NET Framework 2.0 are found in the System.Collections.Generic namespace. 여기에는 List<T>, Dictionary<TKey,TValue> 등이 포함됩니다.These include List<T>, Dictionary<TKey,TValue>, and so on. 이러한 클래스는 .NET Framework 1.0 클래스에 비해 형식 안정성 및 성능을 향상시킵니다.These classes provide improved type safety and performance compared to the .NET Framework 1.0 classes. 그러나 .NET Framework 2.0 컬렉션 클래스는 스레드 동기화를 제공하지 않습니다. 여러 스레드에서 동시에 항목이 추가되거나 제거되는 경우 사용자 코드에서는 모든 동기화를 제공해야 합니다.However, the .NET Framework 2.0 collection classes do not provide any thread synchronization; user code must provide all synchronization when items are added or removed on multiple threads concurrently.

.NET Framework 4의 동시 컬렉션 클래스는 .NET Framework 2.0 컬렉션 클래스의 형식 안전성을 제공할 뿐만 아니라 .NET Framework 1.0 컬렉션이 제공하는 스레드로부터의 안전성보다 더 효율적이고 안전하기 때문에 권장됩니다.We recommend the concurrent collections classes in the .NET Framework 4 because they provide not only the type safety of the .NET Framework 2.0 collection classes, but also more efficient and more complete thread safety than the .NET Framework 1.0 collections provide.

세부적인 잠금 및 잠금 해제 메커니즘Fine-Grained Locking and Lock-Free Mechanisms

동시 컬렉션 형식의 일부에서는 .NET Framework 4에 새로 도입된 SpinLock, SpinWait, SemaphoreSlimCountdownEvent와 같은 간단한 동기화 메커니즘을 사용합니다.Some of the concurrent collection types use lightweight synchronization mechanisms such as SpinLock, SpinWait, SemaphoreSlim, and CountdownEvent, which are new in the .NET Framework 4. 실제로 이러한 동기화 형식이 스레드를 Wait 상태로 전환하기 전 짧은 기간 동안에는 일반적으로 사용 중인 회전을 사용합니다.These synchronization types typically use busy spinning for brief periods before they put the thread into a true Wait state. 대기 시간이 매우 짧을 경우 회전은 비용이 많이 드는 커널 전환을 포함하는 대기보다 훨씬 계산 비용이 적습니다.When wait times are expected to be very short, spinning is far less computationally expensive than waiting, which involves an expensive kernel transition. 회전을 사용하는 컬렉션 클래스의 경우 이 효율성 덕분에 여러 스레드가 매우 빠른 속도로 항목을 추가하고 제거할 수 있습니다.For collection classes that use spinning, this efficiency means that multiple threads can add and remove items at a very high rate. 회전 및 차단에 대한 자세한 내용은 SpinLockSpinWait를 참조하세요.For more information about spinning vs. blocking, see SpinLock and SpinWait.

ConcurrentQueue<T>ConcurrentStack<T> 클래스는 잠금을 전혀 사용하지 않습니다.The ConcurrentQueue<T> and ConcurrentStack<T> classes do not use locks at all. 대신, 스레드로부터의 안전성을 달성하기 위해 Interlocked 작업을 사용합니다.Instead, they rely on Interlocked operations to achieve thread-safety.

참고

동시 컬렉션 클래스가 ICollection을 지원하기 때문에 이러한 속성이 관련되지 않은 경우에도 IsSynchronizedSyncRoot 속성에 대한 구현을 제공합니다.Because the concurrent collections classes support ICollection, they provide implementations for the IsSynchronized and SyncRoot properties, even though these properties are irrelevant. IsSynchronized는 항상 false를 반환하고 SyncRoot는 항상 null(Visual Basic의 Nothing)입니다.IsSynchronized always returns false and SyncRoot is always null (Nothing in Visual Basic).

다음 테이블에서는 System.Collections.Concurrent 네임스페이스의 컬렉션 형식을 나열합니다.The following table lists the collection types in the System.Collections.Concurrent namespace.

형식Type 설명Description
BlockingCollection<T> IProducerConsumerCollection<T>을 구현하는 모든 형식에 대해 경계 및 차단 기능을 제공합니다.Provides bounding and blocking functionality for any type that implements IProducerConsumerCollection<T>. 자세한 내용은 BlockingCollection 개요를 참조하세요.For more information, see BlockingCollection Overview.
ConcurrentDictionary<TKey,TValue> 키-값 쌍의 사전을 스레드로부터 안전하게 구현합니다.Thread-safe implementation of a dictionary of key-value pairs.
ConcurrentQueue<T> FIFO(선입선출) 큐를 스레드로부터 안전하게 구현합니다.Thread-safe implementation of a FIFO (first-in, first-out) queue.
ConcurrentStack<T> LIFO(후입선출) 스택을 스레드로부터 안전하게 구현합니다.Thread-safe implementation of a LIFO (last-in, first-out) stack.
ConcurrentBag<T> 요소의 순서 없는 컬렉션을 스레드로부터 안전하게 구현합니다.Thread-safe implementation of an unordered collection of elements.
IProducerConsumerCollection<T> 형식이 BlockingCollection에 사용하도록 구현해야 하는 인터페이스입니다.The interface that a type must implement to be used in a BlockingCollection.
제목Title 설명Description
BlockingCollection 개요BlockingCollection Overview BlockingCollection<T> 형식에서 제공하는 기능에 대해 설명합니다.Describes the functionality provided by the BlockingCollection<T> type.
방법: ConcurrentDictionary에서 항목 추가 및 제거How to: Add and Remove Items from a ConcurrentDictionary ConcurrentDictionary<TKey,TValue>에서 요소를 추가하고 제거하는 방법에 관해 설명합니다.Describes how to add and remove elements from a ConcurrentDictionary<TKey,TValue>
방법: BlockingCollection에서 개별적으로 항목 추가 및 가져오기How to: Add and Take Items Individually from a BlockingCollection 읽기 전용 열거자를 사용하지 않고 차단 컬렉션에서 항목을 추가하고 검색하는 방법에 대해 설명합니다.Describes how to add and retrieve items from a blocking collection without using the read-only enumerator.
방법: 컬렉션에 한계 지정 및 차단 기능 추가How to: Add Bounding and Blocking Functionality to a Collection 컬렉션 클래스를 IProducerConsumerCollection<T> 컬렉션에 대한 기본 스토리지 메커니즘으로 사용하는 방법을 설명합니다.Describes how to use any collection class as the underlying storage mechanism for an IProducerConsumerCollection<T> collection.
방법: ForEach를 사용하여 BlockingCollection의 항목 제거How to: Use ForEach to Remove Items in a BlockingCollection foreach(Visual Basic의 For Each)를 사용하여 차단 컬렉션에서 모든 항목을 제거하는 방법에 대해 설명합니다.Describes how to use foreach, (For Each in Visual Basic) to remove all items in a blocking collection.
방법: 파이프라인에서 차단 컬렉션 배열 사용How to: Use Arrays of Blocking Collections in a Pipeline 파이프라인을 구현하는 동시에 여러 차단 컬렉션을 사용하는 방법에 대해 설명합니다.Describes how to use multiple blocking collections at the same time to implement a pipeline.
방법: ConcurrentBag을 사용하여 개체 풀 만들기How to: Create an Object Pool by Using a ConcurrentBag 개체를 끊임없이 새로 만드는 대신 다시 사용할 수 있는 시나리오에서 동시 모음을 사용하고 성능을 향상시키는 방법을 보여 줍니다.Shows how to use a concurrent bag to improve performance in scenarios where you can reuse objects instead of continually creating new ones.

참고Reference

System.Collections.Concurrent