스레드 잠금
스레드 잠금은 공유 리소스에 대한 액세스를 보호하는 데 사용되는 중요 구역 개체와 같은 스레딩 기본 요소를 기다리는 동안 스레드가 중단될 때 발생합니다. 두 스레드가 동시에 공유 리소스에 액세스하려고 할 경우 스레드 중 한 개가 일시 중단 상태가 됩니다. (자세한 내용은 스레드 상태 이해를 참조하세요.) 일시 중단된 스레드는 공유 리소스를 사용할 수 있을 때까지 계속 실행할 수 없습니다.
PIX
PIX의 타임라인 창에서 스레드가 실행 중인 경우, 실행 중인 코어와 스레드가 전환된 이유를 관찰하여 스레드가 잠겨 있는 위치를 볼 수 있습니다.
스레드가 코드로 잠겨 있는 위치를 찾으면
타이밍 캡처를 생성하기 위한 일반 단계를 수행합니다.
그림 1. 타이밍 캡처를 표시하는 PIX의 타임라인 창
그림 1에 표시된 빨간색의 각 빨간색 선은 컨텍스트 전환을 나타냅니다. 빨간색 부분이 더 굵은 경우 여러 컨텍스트 전환이 함께 닫히게 됩니다.
여러 컨텍스트 전환이 포함된 관심 지역을 확대합니다.
그림 2: PIX의 타임라인 창의 확장된 구역
참고 항목
각 타임라인 레이블 왼쪽에 있는 기어 아이콘을 선택하여 컨텍스트 전환을 개선하여 보기 쉽게 만드는 등의 보기 옵션을 표시할 수 있습니다.
그림 2에서 각 스레드 타임라인의 위쪽 막대 끝에 있는 세로 밝은 붉은색 선을 볼 수 있습니다. 각 줄은 컨텍스트 전환을 나타냅니다.
컨텍스트 전환 위로 마우스를 가져 가면 기본 정보가 표시됩니다. 컨텍스트 전환에서 실행을 시작하는 스레드가 다른 스레드에 의해 준비 상태로 전환된 경우 그림 3과 같이 두 스레드 타임라인 사이에 화살표가 나타납니다.
그림 3. 컨텍스트 전환 세부 정보를 표시하는 PIX의 타임라인 창
컨텍스트 전환에 대한 줄을 클릭하여 선택합니다. 이제 그림 4에 표시된 같이 타임라인 탭의 왼쪽 아래에 있는 요소 세부 정보 창을 살펴보세요. 창에는 스레드 전환 아웃(From), 스레드 전환 인(To) 및 사용 가능한 경우 스레드에 의해 준비됨이 표시됩니다. 이 예에서 컨텍스트 전환은 유휴 상태에서 스레드 792로, 스레드 756에 의해 준비됩니다.
그림 4. 호출 스택을 표시하는 컨텍스트 전환의 PIX 요소 세부 정보 창
대상(To) 호출 스택에서 스레드 792가 Windows 이벤트 개체에 대한 래퍼인
lock
개체에 대한ATG::EventLockable
호출에서 재개되었음을 볼 수 있습니다. 준비 스레드 (756)가 동일한 개체에서unlock
을(를) 호출했습니다. 두 스레드 모두 동일한AcquireLockAndSpin
함수를 호출했습니다. 이 예제에서 컨텍스트 전환은 스레드 756에 의해 준비되었으며 스레드 792가 대기 중인 Windows 이벤트를 설정했습니다.참고 항목
모든 컨텍스트 스위치에 "readied by(준비자)" 데이터가 있는 것은 아닙니다. 예를 들어 절전 모드에서 깨어난 스레드에는 컨텍스트 전환에 나열된 "준비된" 스레드가 없습니다.
WPA
Windows Performance Analyzer(WPA)를 사용하여 스레드가 잠기는 위치를 찾을 수도 있습니다. 잠금 스레드를 검색하는 데 사용할 수 있는 가장 좋은 두 가지 보기는 프로세스, 스레드별 CPU 사용량(정밀) 타임라인 및 CPU별 CPU 사용량 (정밀) 타임라인이며 두 가지 모두 ThreadLocking.wpaProfile이라는 프로필 WPA에 있습니다. 이러한 보기는 컨텍스트 스위치를 기반으로 하며 언제 스레드가 전환되는지와 새 스레드의 호출 스택을 정확하게 보여줍니다.
이벤트 추적 로그 (ETL) 파일을 생성하려면 일반 단계를 수행하세요.
ThreadLocking.wpaProfile WPA 프로필을 적용합니다. 새 분석 탭은 그림 5와 같아야 합니다.
그림 5. WPA에서 스레드 잠금 프로필의 기본 보기
이 두 가지 보기는 동일한 데이터를 볼 수 있는 다른 방법입니다. 문제가 특정 스레드나 CPU 코어와 관련되어 있는지에 따라 각 보기에 이점이 있을 수 있습니다. 이 예제에서는 프로세스, 스레드 보기만 사용합니다. 그러나 문제가 더 일반적이거나 CPU 코어에 국한된 경우 CPU보기에서 동일한 단계를 사용할 수 있습니다.
관심 있는 스레드를 선택하세요. 해당 스레드가 실행 중인 모든 시간 프레임이 그래프에서 강조 표시됩니다.
타임라인의 한 섹션을 확대합니다. 이렇게 하면 실행 중일 수 있는 다른 스레드의 노이즈를 제거하는 데 도움이 됩니다. 좋은 시작점은 단일 프레임입니다.
상당한 시간 동안 전환된 후 방금 실행을 시작한 스레드 또는 상당한 횟수 동안 시작 및 중지된 스레드에서 위치를 찾으세요. 그림 6과 같이 해당 위치를 확대합니다.
그림 6. 프로세싱에서 스레드가 전환되는 시간 프레임으로 확대
그림 7과 같이 표에서 일치하는 섹션을 강조 표시하려면 그래프 내에서 특정 스레드 또는 시간 프레임을 선택합니다. 새 스레드 스택(프레임 태그) 열에는 스레드가 이전에 전환된 코드의 호출 스택이 표시됩니다. 개수 열에는 현재 타임 라인보기에 표시되는 스레드 부분에 대한 모든 컨텍스트 스위치에 해당 호출 스택의 프레임이 있는 숫자가 표시됩니다.
그림 7. EventLockable::lock이 WaitForSingleObjectEx를 호출했기 때문에 4번 전환되었음을 보여주는 스레드 1084에 대한 스레드 타임라인
스레드는 다양한 이유로 인해 꺼질 수 있습니다. 다양한 위치와 스레드를 확대하면 코드에서 발생하는 상황을 보다 명확하게 파악할 수 있습니다. 예를 들어 스레드 1084의 4개 컨텍스트 전환은 스택 끝의 데이터 테이블 아래에 개별적으로 나열됩니다. 열의 너비를 조정하면 준비 스레드 스택 열(그림 8)에서 특정 컨텍스트 전환의 준비 스레드를 보여주는 정보를 볼 수 있습니다.
그림 8. WPA 데이터 테이블은 1084 스레드에 대한 하나의 컨텍스트 전환이 ATG::EventLockable::unlock를 통해 1076에 의해 준비되었음을 보여줍니다:
스레드 잠금의 일반적인 원인
스레드는 다양한 이유로 잠길 수 있습니다. 다음은 가장 일반적인 이유와 이에 대해 수행할 작업입니다.
- 스핀 잠금에서 SwitchToThread를 사용하는 엄격한 루프
- 스핀 잠금 장치에 높은 경합이 발생합니다.
- 스핀 개수 연장을 고려해 보세요.
-
EnterCriticalSection으로 호출됩니다.
- 중요한 부분에서 높은 경합이 발생합니다.
- 스핀 개수 연장을 고려해 보세요.
-
단일 개체 대기
- 스레드 통신이 너무 높습니다.
- 원시 알고리즘이 필요하지 않은 다른 알고리즘을 생각해 보세요.
- 메시지를 배치하여 통신을 최소화합니다.
- 수행할 작업이 부족합니다.
- 작업 복잡성을 높이는 방안을 고려하세요.
- 새 작업이 준비되기 전에 작업이 완료됩니다.
- 차단하기 전에
WaitForSingleObject
의 스핀을 검토하세요.
- 차단하기 전에
- 스레드 통신이 너무 높습니다.
-
우선 순위 반전
- 낮은 우선순위 스레드는 높은 우선순위 스레드에 필요한 잠금을 보유합니다.