다중 스레딩을 위한 데이터 동기화

다중 스레드가 단일 개체의 속성 및 메서드에 대한 호출을 할 수 있는 경우 해당 호출을 동기화하는 것은 중요합니다. 그렇지 않으면 하나의 스레드는 다른 스레드가 수행하는 작업을 중단시킬 수 있으며 개체는 잘못된 상태로 남을 수 있습니다. 멤버가 그러한 중단으로부터 보호되는 클래스를 스레드로부터 안전하다고 합니다.

.NET은 인스턴스 및 정적 멤버에 대한 액세스를 동기화하는 여러 전략을 제공합니다.

  • 동기화된 코드 영역. Monitor 클래스 또는 이 클래스에 대한 컴파일러 지원을 사용하여 성능을 향상시키는 필요한 코드 블록만을 동기화할 수 있습니다.

  • 수동 동기화. .NET 클래스 라이브러리에서 제공하는 동기화 개체를 사용할 수 있습니다. Monitor 클래스에 대한 설명을 포함하는 동기화 기본 형식 개요를 참조하세요.

  • 동기화된 컨텍스트. .NET Framework 및 Xamarin 애플리케이션의 경우에만 SynchronizationAttribute를 사용하여 ContextBoundObject 개체에 대한 간단한 자동 동기화를 사용하도록 설정할 수 있습니다.

  • System.Collections.Concurrent 네임스페이스의 컬렉션 클래스. 이러한 클래스는 기본 제공 동기화된 추가 및 제거 작업을 제공합니다. 자세한 내용은 스레드로부터 안전한 컬렉션을 참조하세요.

공용 언어 런타임은 클래스가 요구 사항에 따라 다양한 서로 다른 방식으로 동기화될 수 있는 범주의 수로 나뉘는 스레드 모델을 제공합니다. 다음 표는 지정된 동기화 범주로 필드 및 메서드에 대해 제공되는 동기화 지원을 보여 줍니다.

범주 전역 필드 정적 필드 정적 메서드 인스턴스 필드 인스턴스 메서드 특정 코드 블록
동기화 없음 아니요 없음 없음 없음 없음 아니요
동기화된 컨텍스트 아니요 없음 없음 아니요
동기화된 코드 영역 아니요 아니요 표시된 경우에만 아니요 표시된 경우에만 표시된 경우에만
수동 동기화 수동 수동 수동 수동 수동 수동

동기화 없음

이것은 개체의 기본값입니다. 모든 스레드는 언제든지 모든 메서드 또는 필드에 액세스할 수 있습니다. 한 번에 하나의 스레드만 이러한 개체에 액세스해야 합니다.

수동 동기화

.NET 클래스 라이브러리는 스레드 동기화에 대한 다양한 클래스를 제공합니다. 동기화 기본 형식 개요를 참조하세요.

동기화된 코드 영역

Monitor 클래스 또는 컴파일러 키워드를 사용하여 코드 블록, 인스턴스 메서드 및 정적 메서드를 동기화할 수 있습니다. 동기화된 정적 필드에 대한 지원은 없습니다.

Visual Basic 및 C#은 특정 언어 키워드를 사용하여 코드 블록의 표시를 지원합니다(C#에서 lock 문 또는 Visual Basic에서 SyncLock 문). 스레드에 의해 코드가 실행되면 잠금을 얻으려는 시도가 이루어집니다. 다른 스레드가 잠금을 이미 획득한 경우 잠금을 사용할 수 있게 될 때까지 해당 스레드는 차단됩니다. 스레드가 동기화된 코드 블록을 종료하면 스레드가 블록을 종료하는 방법에 관계 없이 잠금이 해제됩니다.

참고 항목

동기화된 영역 내에서 Monitor의 다른 메서드와 함께 사용할 수 있도록 Monitor.EnterMonitor.Exit을 사용하여 lockSyncLock 문이 구현됩니다.

Monitor 또는 컴파일러 키워드 중 하나를 사용하여 전체 메서드의 본문을 잠그는 것과 동일한 효과를 가지는 MethodImplOptions.Synchronized의 값이 있는 MethodImplAttribute를 사용하여 메서드를 데코레이팅할 수도 있습니다.

Thread.Interrupt를 사용하여 동기화된 코드 영역에 대한 액세스를 기다리는 것과 같은 차단 작업에서 스레드를 중단시킬 수 있습니다. Thread.Sleep과 같은 작업에서 스레드를 중단시키는 데도 Thread.Interrupt가 사용됩니다.

Important

static 메서드(Visual Basic에서 Shared 메서드)를 보호하기 위해 형식(C#에서 typeof(MyType), Visual Basic에서 GetType(MyType) 또는 C++에서 MyType::typeid)을 잠그지 마세요. 전용 정적 개체를 대신 사용합니다. 마찬가지로 인스턴스 메서드를 잠그는 데 C#에서 this(Visual Basic에서 Me)를 사용하지 마세요. 전용 개체를 대신 사용합니다. 잠재적으로 교착 상태 또는 성능 문제를 발생시키는 사용자 고유의 것 이외의 코드에서 클래스 또는 인스턴스를 잠글 수 있습니다.

컴파일러 지원

Visual Basic 및 C#은 Monitor.EnterMonitor.Exit를 사용하여 개체를 잠그는 언어 키워드를 지원합니다. Visual Basic은 SyncLock 문을 지원하고 C#은 lock 문을 지원합니다.

두 경우 모두 코드 블록에서 예외가 throw되는 경우 lock 또는 SyncLock으로 획득된 잠금이 자동으로 해제됩니다. C# 및 Visual Basic 컴파일러는 시도의 초반에 Monitor.Entertry/finally 블록을 내보내고 finally 블록에서 Monitor.Exit을 내보냅니다. lock 또는 SyncLock 블록 내에서 예외가 throw되는 경우 finally 처리기가 정리 작업을 수행할 수 있도록 실행됩니다.

동기화된 컨텍스트

.NET Framework 및 Xamarin 애플리케이션에서만 모든 ContextBoundObjectSynchronizationAttribute를 사용하여 모든 인스턴스 메서드와 필드를 동기화할 수 있습니다. 동일한 컨텍스트 도메인에 있는 모든 개체는 동일한 잠금을 공유합니다. 여러 스레드가 메서드 및 필드에 액세스할 수 있지만 한 번에 하나의 스레드만 허용됩니다.

참고 항목