다음을 통해 공유


스레드로부터 안전한 구성 요소

스레드 간 리소스 공유는 다중 스레드 프로그래밍에서 자주 사용됩니다.예를 들어, 여러 스레드에서 공유 데이터베이스에 액세스하거나 시스템 변수 집합을 업데이트할 수도 있습니다.둘 이상의 스레드에서 동시에 공유 리소스에 경쟁적으로 액세스하면 경합 상태가 발생할 수 있습니다.한 스레드에서 리소스를 잘못된 상태로 수정하고 나서 다른 스레드에서 이 리소스에 액세스하여 잘못된 상태의 리소스를 사용할 때 경합 상태가 발생합니다.다음 예제를 참조하십시오.

Public Class WidgetManipulator
Public TotalWidgets as Integer = 0
Public Sub AddWidget()
   TotalWidgets += 1
   Console.WriteLine("Total widgets = " & TotalWidgets.ToString)
End Sub
Public Sub RemoveWidgets()
   TotalWidgets -= 10
End Sub
End Class
public class WidgetManipulator
{
   public int TotalWidgets = 0;
   public void AddWidget()
   {
      TotalWidgets++;
      Console.WriteLine("Total widgets = " + TotalWidgets.ToString());
   }
   public void RemoveWidgets()
   {
      TotalWidgets -= 10;
   }
}

이 클래스에서는 두 개의 메서드를 노출합니다.첫 번째 메서드인 AddWidget 메서드는 TotalWidgets 필드 값에 1을 더하고 결과를 콘솔에 표시합니다.두 번째 메서드는 TotalWidgets 값에서 10을 뺍니다.두 스레드에서 동시에 같은 WidgetManipulator 클래스 인스턴스에 액세스하려는 경우를 가정해 봅니다.한 스레드에서 AddWidget을 호출하고 동시에 다른 스레드에서 RemoveWidgets을 호출할 수도 있습니다.이 경우 첫 번째 스레드에서 정확한 값을 보고하기 전에 두 번째 스레드에서 TotalWidgets 값을 변경할 수도 있습니다.이러한 경합 상태로 인해 올바르지 않은 결과가 보고되고 데이터가 손상될 수 있습니다.

잠금을 사용하여 경합 상태 방지

잠금을 사용하면 코드의 주요 섹션을 경합 상태에서 보호할 수 있습니다.잠금은 Visual Basic 키워드 SyncLock 문 또는 C# 키워드 lock 문으로 표시되며, 이를 사용하면 실행의 단일 스레드에서 개체에 대한 단독 실행 권한을 얻을 수 있습니다.다음 예제에서는 잠금을 설정하는 방법을 보여 줍니다.

SyncLock MyObject
' Insert code that affects MyObject.
End SyncLock
lock(MyObject)
{
   // Insert code that affects MyObject.
}

잠금 시작 부분에 이르면 스레드에서 지정된 개체(위 예제에서는 MyObject)에 대한 단독 액세스 권한을 얻을 때까지 개체에 대한 실행이 차단됩니다.잠금의 끝부분에 도달하면 잠금이 해제되고 실행이 정상적으로 진행됩니다.참조를 반환하는 개체에만 잠금을 설정할 수 있으며값을 반환하는 개체에 대해서는 이 방식으로 잠금을 설정할 수 없습니다.

a8544e2s.collapse_all(ko-kr,VS.110).gif잠금의 단점

잠금을 사용하면 여러 스레드에서 동시에 한 개체에 액세스하지 못하도록 할 수 있지만 이로 인해 성능이 크게 저하될 수도 있습니다.서로 다른 많은 스레드를 실행하는 프로그램을 가정해 봅니다.각 스레드에서 특정 개체를 사용해야 하고 그 개체에 대한 단독 잠금을 얻을 때까지 기다린 다음에야 실행할 수 있다면, 스레드들이 모두 실행을 멈춘 상태로 줄지어 대기하게 되어 성능이 떨어질 수 있습니다.따라서 한 단위로 실행되어야 하는 코드에서만 잠금을 사용해야 합니다.예를 들어, 상호 의존적인 여러 리소스를 업데이트할 수 있습니다.이러한 코드를 원자라고 합니다.원자적으로 실행되는 코드에서만 잠금을 사용하도록 제한하면 좋은 성능을 유지하면서도 데이터의 안전성이 보장되는 다중 스레드 구성 요소를 작성할 수 있습니다.

또한 교착 상태가 발생할 수 있는 상황을 방지해야 합니다.이 경우 여러 스레드가 서로 공유된 리소스가 해제될 때까지 기다립니다.예를 들어 스레드 1이 리소스 A를 단독으로 잠그고 있고 리소스 B를 기다리는 반면,스레드 2는 리소스 B를 잠그고 있고 리소스 A를 기다릴 수 있습니다.이 경우 두 스레드 모두 진행되지 않습니다.교착 상태 상황을 방지하려면 세심한 프로그래밍이 필요합니다.

참고 항목

작업

방법: 다중 스레드 실행 조정

방법: 스레드에서 컨트롤 조작

연습: Visual Basic으로 간단한 다중 스레드 구성 요소 만들기

연습: Visual C#으로 간단한 다중 스레드 구성 요소 만들기

참조

BackgroundWorker

개념

이벤트 기반 비동기 패턴 개요

기타 리소스

구성 요소에서 다중 스레딩