스레드 경합이란 무엇입니까?


120

누군가 스레드 경합이 무엇인지 간단히 설명해 주시겠습니까?

나는 그것을 봤지만 간단한 설명을 찾을 수없는 것 같습니다.


9
그래서 당신의 모호한 생각이 무엇인지 적어 두십시오. 그러면 우리는 당신이 어디에서 벗어나거나 당신의 이해가 정확할 수 있습니다.
James Black

답변:


87

기본적으로 스레드 경합은 한 스레드가 현재 다른 스레드가 보유하고있는 잠금 / 오브젝트를 기다리는 상태입니다. 따라서이 대기 스레드는 다른 스레드가 특정 개체의 잠금을 해제 할 때까지 해당 개체를 사용할 수 없습니다.


53
이 답변은 불완전합니다 (대부분의 다른 답변과 마찬가지로). 자물쇠는 다툼이있을 수있는 한 가지 유형이지만, 그러한 유일한 것과는 거리가 멀다. 잠금없는 리소스에 대한 경합도있을 수 있습니다. (예를 들어 두 개의 스레드가 동일한 정수를 원자 적으로 계속 증가 시키면 캐시 핑퐁으로 인해 경합이 발생할 수 있습니다. 잠금이 관련되지 않습니다.)
David Schwartz

스레드가 항상 GIL을 획득해야하는 CPython과 같은 GIL (Global Interpreter Lock)의 경우 동일한 프로세스에서 실행중인 여러 스레드가 기본적으로 경합 상태에 있습니다.
Acumenus 2013

나는 당신이 그것을 교착 상태로 설명했다고 생각하지만 교착 상태와는 매우 다릅니다.
Harshit Gupta 2015 년

185

몇 가지 답변이 잠금 경합에 초점을 맞추는 것처럼 보이지만 잠금이 경합을 경험할 수있는 유일한 리소스는 아닙니다. 경합은 단순히 두 스레드가 동일한 리소스 또는 관련 리소스에 액세스하려고 할 때 경합 스레드 중 하나 이상이 다른 스레드가 실행 중이 아닐 때보 다 느리게 실행되는 경우입니다.

경합의 가장 확실한 예는 잠금입니다. 스레드 A에 잠금이 있고 스레드 B가 동일한 잠금을 얻으려면 스레드 B가 스레드 A가 잠금을 해제 할 때까지 기다려야합니다.

이제 이것은 플랫폼에 따라 다르지만 다른 스레드가 잠금을 해제 할 때까지 기다릴 필요가 없더라도 스레드가 느려질 수 있습니다! 이는 잠금이 어떤 종류의 데이터를 보호하고 데이터 자체도 종종 경합되기 때문입니다.

예를 들어, 잠금을 획득하고 객체를 수정 한 다음 잠금을 해제하고 다른 작업을 수행하는 스레드를 생각해보십시오. 두 스레드가이 작업을 수행하는 경우 잠금을 위해 싸우지 않더라도 스레드는 하나의 스레드 만 실행 중일 때보 다 훨씬 느리게 실행될 수 있습니다.

왜? 각 스레드가 최신 x86 CPU의 자체 코어에서 실행 중이고 코어가 L2 캐시를 공유하지 않는다고 가정합니다. 스레드가 하나만 있으면 객체가 대부분 L2 캐시에 남아있을 수 있습니다. 두 스레드가 모두 실행되면 한 스레드가 객체를 수정할 때마다 다른 스레드는 다른 CPU가 캐시 라인을 무효화했기 때문에 데이터가 L2 캐시에 없다는 것을 알게됩니다. 예를 들어 Pentium D에서는 코드가 L2 캐시 속도보다 훨씬 낮은 FSB 속도로 실행됩니다.

잠금 자체가 경합되지 않더라도 경합이 발생할 수 있으므로 잠금이 없을 때 경합이 발생할 수도 있습니다. 예를 들어 CPU가 32 비트 변수의 원자 적 증분을 지원한다고 가정 해 보겠습니다. 한 스레드가 변수를 계속 증가 및 감소 시키면 해당 변수는 대부분 캐시에서 뜨겁습니다. 두 개의 스레드가이를 수행하면 해당 캐시는 해당 변수를 보유한 메모리의 소유권을두고 경쟁하게되며 캐시 일관성 프로토콜이 캐시 라인의 각 코어 소유권을 보호하기 위해 작동하므로 많은 액세스가 느려집니다.

아이러니하게도 잠금은 일반적으로 경합을 입니다. 왜? 잠금이 없으면 두 개의 스레드가 동일한 개체 또는 컬렉션에서 작동 할 수 있으며 많은 경합이 발생할 수 있습니다 (예 : 잠금 해제 대기열이 있음). 잠금은 경합 스레드의 일정을 해제하여 경합이 아닌 스레드가 대신 실행되도록합니다. 스레드 A가 잠금을 보유하고 스레드 B가 동일한 잠금을 원하는 경우 구현은 대신 스레드 C를 실행할 수 있습니다. 스레드 C에 해당 잠금이 필요하지 않으면 스레드 A와 B 간의 향후 경합을 잠시 피할 수 있습니다. (물론, 이것은 실행할 수있는 다른 스레드가 있다고 가정합니다. 시스템 전체가 유용한 진전을 이룰 수있는 유일한 방법이 경합하는 스레드를 실행하는 것이라면 도움이되지 않습니다.)


4
+1 또한이를 명확히하기 위해 두 개의 코어가 싸우고있는 두 변수는 경합을 유발하기 위해 동일한 변수 일 필요도 없으며 동일한 캐시 라인의 메모리에만 저장하면됩니다. 패딩 구조 및 / 또는 구조를 메모리에 정렬하면 이러한 형태의 경합을 방지 할 수 있습니다.
Rob_before_edits 2011

1
더 자세히 답변의 마지막 항을 이해하는 데 도움을 기쁘게 @ 데이비드
학습자

4
@Naroji 그것에 대해 질문하십시오.
David Schwartz

@DavidSchwartz, 당신은 C 프로그래머입니까?
Pacerier 2015 년

@Pacerier C ++ 대부분.
David Schwartz

19

에서 여기 :

경합은 스레드가 쉽게 사용할 수없는 리소스를 기다리고있을 때 발생합니다. 코드 실행 속도가 느려지지만 시간이 지남에 따라 정리 될 수 있습니다.

교착 상태는 스레드가 두 번째 스레드가 잠근 리소스를 기다리고 있고 두 번째 스레드가 첫 번째 스레드가 잠근 리소스를 기다리고있을 때 발생합니다. 두 개 이상의 스레드가 교착 상태에 포함될 수 있습니다. 교착 상태는 스스로 해결되지 않습니다. 종종 전체 응용 프로그램 또는 교착 상태가 발생한 부분이 중지됩니다.


이것은 또한 스레드 경합 및 교착 상태의 차이에 대해 설명
Sankalp

3

질문의 배경에 대해 OP에서 약간의 설명이 있어야한다고 생각합니다. 2 개의 답변을 생각할 수 있습니다 (이 목록에 추가 사항이 있다고 확신합니다).

  1. 스레드 경합의 일반적인 "개념"과 그것이 응용 프로그램에서 어떻게 나타날 수 있는지를 언급하는 경우 위의 @DavidSchwartz의 자세한 답변을 따릅니다.

  2. '.NET CLR Locks and Threads : Total # of Contentions'성능 카운터도 있습니다. 이 카운터에 대한 PerfMon 설명에서 가져온 것처럼 다음과 같이 정의됩니다.

    이 카운터는 CLR의 스레드가 성공적으로 관리 잠금을 획득하려고 시도한 총 횟수를 표시합니다. 관리 잠금은 여러 방법으로 획득 할 수 있습니다. C #에서 "lock"문을 사용하거나 System.Monitor.Enter를 호출하거나 MethodImplOptions.Synchronized 사용자 지정 특성을 사용합니다.

... 다른 OS 및 응용 프로그램 프레임 워크를위한 다른 사람들도 확신합니다.


2

스레드가 2 개 있습니다. 스레드 A와 스레드 B, 객체 C도 있습니다.

A는 현재 개체 C에 액세스하고 있으며 해당 개체에 잠금을 설정했습니다. B는 객체 C에 액세스해야하지만 A가 객체 C에 대한 잠금을 해제 할 때까지 액세스 할 수 없습니다.


1

또 다른 단어는 동시성 일 수 있습니다. 동일한 리소스를 사용하려는 두 개 이상의 스레드에 대한 아이디어입니다.


1

나에게 경합은 공유 리소스에 대한 2 개 이상의 스레드 간의 경쟁입니다. 자원은 자물쇠, 카운터 등이 될 수 있습니다. 경쟁은 "누가 먼저 얻는 지"를 의미합니다. 스레드가 많을수록 더 많은 경합이 발생합니다. 리소스에 더 자주 액세스할수록 더 많은 경합이 발생합니다.


1

다음 시나리오를 상상해보십시오. 내일 최종 시험을 준비하고 있는데 배가 고프다. 그래서 동생에게 10 달러를주고 피자를 사달라고 부탁합니다. 이 경우, 당신은 메인 스레드이고 당신의 형제는 자식 스레드입니다. 주문이 접수되면 귀하와 귀하의 형제는 동시에 일을하고 있습니다 (예 : 피자 공부와 구매). 이제 고려해야 할 두 가지 사례가 있습니다. 첫째, 동생이 피자를 가져 와서 공부하는 동안 끝납니다. 이 경우 공부를 그만두고 피자를 즐길 수 있습니다. 둘째, 공부를 일찍 끝내고 피자를 먹을 수 있기 전에 잠을 잔다 (즉, 오늘 할당 된 직업-내일의 기말 시험 공부-완료). 물론, 당신은 잠을 잘 수 없습니다. 그렇지 않으면 피자를 먹을 기회가 없습니다.

예에서와 같이 두 경우는 경쟁의 의미를 제공합니다.


0

스레드 경합은 I / O 작업의 영향도받습니다. 파일 읽기를 기다리는 스레드의 예는 경합으로 간주 할 수 있습니다. I / O 완료 포트를 솔루션으로 사용하십시오.


0

잠금 경합은 스레드가 다른 스레드 *에서 이미 획득 한 객체에 대한 잠금을 획득하려고 할 때 발생합니다. 객체가 해제 될 때까지 스레드는 차단됩니다 (즉, 대기 상태에 있음). 경우에 따라 이것은 애플리케이션에 부정적인 영향을 미치는 소위 직렬 실행으로 이어질 수 있습니다.

에서 dotTrace 문서

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.