경쟁 조건은 무엇입니까?


982

멀티 스레드 응용 프로그램을 작성할 때 발생하는 가장 일반적인 문제 중 하나는 경쟁 조건입니다.

커뮤니티에 대한 나의 질문은 :

경쟁 조건은 무엇입니까?
그것들을 어떻게 감지합니까?
어떻게 처리합니까?
마지막으로, 당신은 어떻게 발생하지 않도록합니까?


3
에 큰 장이 리눅스 HOWTO를위한 안전 프로그램은 그들이 무엇인지 설명하고, 어떻게이를 방지하는 그.
Craig H

4
언어를 지정하지 않고이 질문의 대부분은 다른 언어로 정의, 결과 및이를 방지하는 도구가 다를 수 있기 때문에 제대로 대답 할 수 없습니다.
MikeMB

@MikeMB. Race Catcher와 같이 바이트 코드 실행을 분석 할 때를 제외하고는 동의했습니다 (이 스레드 stackoverflow.com/a/29361427/1363844 참조 ) 바이트 코드로 컴파일되는 약 62 개 언어를 모두 처리 할 수 ​​있습니다 ( en.wikipedia.org 참조). / wiki / List_of_JVM_languages )
Ben

답변:


1237

경쟁 조건은 둘 이상의 스레드가 공유 데이터에 액세스 할 수 있고 동시에 변경하려고 할 때 발생합니다. 스레드 예약 알고리즘은 언제든지 스레드간에 교환 할 수 있으므로 스레드가 공유 데이터에 액세스하려는 순서를 모릅니다. 따라서, 데이터 변경의 결과는 스레드 스케줄링 알고리즘에 의존한다. 즉, 두 스레드 모두 데이터를 액세스 / 변경하기 위해 "레이싱"하고있다.

하나의 스레드가 "check-then-act"(예 : 값이 X 인 경우 "check", 값은 X 인 값에 의존하는 무언가를 수행하려면 "act")를 수행하고 다른 스레드는 "확인"과 "행위"사이. 예 :

if (x == 5) // The "Check"
{
   y = x * 2; // The "Act"

   // If another thread changed x in between "if (x == 5)" and "y = x * 2" above,
   // y will not be equal to 10.
}

요점은 y가 10이 될 수도 있고 다른 스레드가 검사와 작동 사이에서 x를 변경했는지 여부에 따라 무엇이든 될 수 있습니다. 당신은 알 방법이 없습니다.

경쟁 조건이 발생하지 않도록하려면 일반적으로 한 번에 하나의 스레드 만 데이터에 액세스 할 수 있도록 공유 데이터를 잠그십시오. 이것은 다음과 같은 것을 의미합니다.

// Obtain lock for x
if (x == 5)
{
   y = x * 2; // Now, nothing can change x until the lock is released. 
              // Therefore y = 10
}
// release lock for x

121
다른 스레드가 잠금이 발생하면 어떻게합니까? 기다 립니까? 오류?
Brian Ortiz

173
예, 다른 스레드는 잠금이 해제 될 때까지 기다려야 진행할 수 있습니다. 따라서 홀딩 스레드가 잠금을 완료하면 잠금이 풀리는 것이 매우 중요합니다. 그것이 해제되지 않으면 다른 스레드는 무기한 대기합니다.
Lehane

2
@Ian 멀티 스레드 시스템에서는 항상 자원을 공유해야 할 때가 있습니다. 대안을 제시하지 않고 한 가지 접근법이 나쁘다고 말하는 것은 생산적이지 않습니다. 나는 항상 개선 할 방법을 찾고 있으며 대안이 있다면 기꺼이 연구하고 장단점을 평가할 것입니다.
Despertar

2
@Despertar ... 또한 자원이 항상 milti 스레드 시스템에서 공유되어야하는 경우는 아닙니다. 예를 들어 각 요소를 처리해야하는 배열이있을 수 있습니다. 어레이를 분할하고 각 파티션에 대한 스레드를 가질 수 있으며 스레드는 서로 완전히 독립적으로 작업을 수행 할 수 있습니다.
Ian Warburton 17

12
경쟁이 일어나기 위해서는 단일 스레드가 공유 데이터를 변경하려고 시도하는 반면 나머지 스레드는 읽거나 변경할 수 있습니다.
SomeWittyUsername

213

공유 자원에 액세스하는 멀티 스레드 (또는 병렬) 코드가 예기치 않은 결과를 초래할 수있는 경우 "경합 상태"가 존재합니다.

이 예제를 보자 :

for ( int i = 0; i < 10000000; i++ )
{
   x = x + 1; 
}

이 코드를 한 번에 5 개의 스레드로 실행하면 x WOULD 값은 50,000,000이되지 않습니다. 실제로는 실행마다 다릅니다.

각 스레드가 x 값을 늘리려면 다음을 수행해야하기 때문입니다.

x의 값을 구합니다
이 값에 1을 더하십시오
이 값을 x에 저장

모든 스레드는 언제든지이 프로세스의 모든 단계에있을 수 있으며 공유 리소스가 관련 될 때 서로 밟을 수 있습니다. x의 상태는 x를 읽는 시간과 다시 쓰는 시간 동안 다른 스레드에 의해 변경 될 수 있습니다.

스레드가 x 값을 검색하지만 아직 저장하지 않았다고 가정 해 봅시다. 다른 스레드도 동일한 값의 x를 검색 할 수 있으며 (스레드가 아직 변경되지 않았기 때문에) 동일한 값 (x + 1)을 다시 x에 저장합니다 !

예:

스레드 1 : x를 읽고 값은 7입니다.
스레드 1 : x에 1을 더하면 값은 8입니다.
스레드 2 : x를 읽고 값은 7입니다.
스레드 1 : x를 8로 저장
스레드 2 : 1을 x에 더하고 값은 8입니다.
스레드 2 : x에 8을 저장

공유 리소스에 액세스하는 코드 앞에 일종의 잠금 메커니즘 을 사용하여 경쟁 조건을 피할 수 있습니다 .

for ( int i = 0; i < 10000000; i++ )
{
   //lock x
   x = x + 1; 
   //unlock x
}

여기서 대답은 매번 50,000,000으로 나타납니다.

잠금에 대한 자세한 내용은 뮤텍스, 세마포어, 중요 섹션, 공유 리소스를 검색하십시오.


이러한 문제가 어떻게 발생하는지 테스트하는 프로그램의 예는 jakob.engbloms.se/archives/65 를 참조하십시오. 실제로 실행중인 시스템의 메모리 모델에 따라 다릅니다.
jakobengblom2 2

1
천만에 멈춰야한다면 어떻게 5 천만에이를 수 있을까요?

9
@nocomprende : 스 니펫 바로 아래에 설명 된대로 5 개의 스레드가 한 번에 동일한 코드를 실행합니다.
Jon Skeet

4
@ JonSkeet 당신이 맞아, 나는 i와 x를 혼동했다. 감사합니다.

싱글 톤 패턴을 구현할 때 이중 점검 잠금이 경쟁 조건을 방지하는 예입니다.
Bharat Dodeja

150

경쟁 조건이란 무엇입니까?

오후 5시에 영화를 보러 갈 계획입니다. 오후 4시에 티켓의 가용성에 대해 문의하십시오. 담당자는 이용 가능하다고 말합니다. 공연 5 분 전에 휴식을 취하고 티켓 창에 도착하십시오. 나는 당신이 무슨 일이 일어 났는지 추측 할 수 있다고 확신합니다 : 그것은 풀 하우스입니다. 여기서 문제는 점검과 조치 사이의 기간에있었습니다. 당신은 4시에 물었고 5시에 행동했습니다. 그동안 누군가 다른 사람이 티켓을 bb습니다. 이는 경쟁 조건입니다. 특히 경쟁 조건에 대한 "확인 후 행동"시나리오입니다.

당신은 그들을 어떻게 감지합니까?

종교적 코드 검토, 다중 스레드 단위 테스트. 바로 가기가 없습니다. 여기에는 Eclipse 플러그인이 거의 없지만 아직 안정된 것은 없습니다.

어떻게 처리하고 방지합니까?

가장 좋은 방법은 부작용이없고 상태 비 저장 기능을 만들고 가능한 한 불변을 사용하는 것입니다. 그러나 이것이 항상 가능한 것은 아닙니다. 따라서 java.util.concurrent.atomic을 사용하면 동시 데이터 구조, 적절한 동기화 및 액터 기반 동시성이 도움이됩니다.

동시성에 가장 적합한 리소스는 JCIP입니다. 위의 설명에 대한 자세한 내용은 여기를 참조하십시오 .


코드 검토 및 단위 테스트는 귀 사이의 흐름을 모델링하고 공유 메모리를 덜 사용하는 데있어 부차적입니다.
Acumenus

2
나는 경쟁 조건의 실제 예를 높이 평가했습니다
Tom O.

11
대답처럼 엄지 손가락 . 해결책은 mutex를 사용하여 4-5 사이의 티켓을 잠그는 것입니다 (상호 예외, C ++). 현실에서는 이것을 티켓 예약이라고합니다 :)
Volt

1
당신은 자바 전용 비트를 떨어 뜨리면 괜찮은 해답이 될 것입니다 (질문 자바에 대한 것이 아니라 일반적으로 오히려 경쟁 조건)
코리 골드버그

아니요. 경쟁 조건이 아닙니다. "비즈니스"관점에서 당신은 너무 오래 기다렸습니다. 분명히 이월 주문은 해결책이 아닙니다. 다만 보험 등 티켓 구입 그렇지 않으면 암표상을 시도
csherriff

65

경쟁 조건과 데이터 경쟁간에 중요한 기술적 차이가 있습니다. 대부분의 답변은 이러한 용어가 동일하다고 가정하지만 그렇지는 않습니다.

데이터 레이스는 2 개의 명령어가 동일한 메모리 위치에 액세스 할 때 발생하며, 이러한 액세스 중 적어도 하나는 쓰기이며 이러한 액세스 중 순서 전에 발생 하지 않습니다 . 이제 주문하기 전에 발생하는 것은 많은 논쟁의 대상이지만 일반적으로 동일한 잠금 변수의 ulock-lock 쌍과 동일한 조건 변수의 대기 신호 쌍은 사전 순서를 유발합니다.

경쟁 조건은 의미 상 오류입니다. 잘못된 프로그램 동작으로 이어지는 이벤트의 타이밍 또는 순서에 발생하는 결함입니다 .

많은 경쟁 조건이 데이터 경쟁으로 인해 발생할 수 있지만 실제로는 그렇지 않습니다. 사실, 데이터 경쟁과 경쟁 조건은 서로에게 필요한 조건도 충분하지도 않습니다. 블로그 게시물은 간단한 은행 거래 예제를 통해 차이점을 잘 설명합니다. 차이점을 설명하는 또 다른 간단한 예가 있습니다.

이제 용어를 정리 했으므로 원래 질문에 대답하려고합니다.

경쟁 조건이 의미 상 버그라는 점을 감안할 때 일반적인 버그 감지 방법은 없습니다. 일반적인 경우에 올바른 프로그램 동작과 잘못된 프로그램 동작을 구별 할 수있는 자동화 된 Oracle을 보유 할 방법이 없기 때문입니다. 레이스 감지는 결정 불가능한 문제입니다.

반면에 데이터 레이스는 정확성과 반드시 ​​관련이없는 정확한 정의를 가지므로이를 감지 할 수 있습니다. 다양한 데이터 레이스 탐지기 (정적 / 동적 데이터 레이스 감지, 잠금 기반 데이터 레이스 감지, 이전 데이터 레이스 감지, 하이브리드 데이터 레이스 감지)가 있습니다. 최첨단 동적 데이터 레이스 검출기는 ThreadSanitizer 로, 실제로 매우 잘 작동합니다.

일반적으로 데이터 경쟁을 처리하려면 공유 데이터에 대한 액세스 사이 (개발 중 또는 위에서 언급 한 도구를 사용하여 감지 된 경우) 사이의 에지를 유발하는 프로그래밍 규칙이 필요합니다. 이것은 잠금, 조건 변수, 세마포어 등을 통해 수행 될 수 있습니다. 그러나 구성에 의한 데이터 경쟁을 피하는 메시지 공유 (공유 메모리 대신)와 같은 다른 프로그래밍 패러다임을 사용할 수도 있습니다.


경쟁 조건을 이해하려면 차이가 중요합니다. 감사!
ProgramCpp

37

표준 정렬 정의는 " 두 개의 스레드가 동시에 메모리의 동일한 위치에 액세스하고 액세스 중 하나 이상이 쓰기 "인 경우입니다. 상황에서 "리더"스레드는 "레이스를이기는"스레드에 따라 이전 값 또는 새 값을 얻을 수 있습니다. 이것이 항상 버그는 아니지만 실제로는 털이 많은 저수준 알고리즘이 의도적으로이를 수행하지만 일반적으로 피해야합니다. @Steve Gury는 언제 문제가 될 수 있는지에 대한 좋은 예입니다.


3
경쟁 조건이 어떻게 유용한 지 예를 들어 주시겠습니까? 인터넷 검색은 도움이되지 않았습니다.
Alex V.

3
@Alex V.이 시점에서 나는 내가 무슨 말을했는지 전혀 모른다. 나는 이것이 잠금이없는 프로그래밍에 대한 참조 일 것이라고 생각하지만 경쟁 조건 자체에 달려 있다고 말하는 것은 실제로 정확하지 않습니다.
Chris Conway

33

경쟁 조건은 일종의 버그이며 특정 시간적 조건에서만 발생합니다.

예 : 두 개의 스레드 A와 B가 있다고 가정하십시오.

스레드 A에서 :

if( object.a != 0 )
    object.avg = total / object.a

스레드 B에서 :

object.a = 0

객체 A를 검사 한 직후에 스레드 A가 선점되면 a는 null이 아니고 B는 수행 a = 0하고 스레드 A가 프로세서를 확보하면 "0으로 나누기"를 수행합니다.

이 버그는 스레드 A가 if 문 바로 뒤에 선점 된 경우에만 발생하지만 매우 드물지만 발생할 수 있습니다.


21

경쟁 조건은 소프트웨어와 관련이있을뿐만 아니라 하드웨어와도 관련이 있습니다. 실제로이 용어는 처음에 하드웨어 산업에서 만들어졌습니다.

Wikipedia 에 따르면 :

이 용어 는 출력영향미치기 위해 서로 경주 하는 두 신호 의 개념에서 비롯됩니다 .

논리 회로의 경쟁 조건 :

여기에 이미지 설명을 입력하십시오

소프트웨어 산업은이 용어를 수정하지 않고 이해하기가 조금 어려웠습니다.

소프트웨어 세계에 매핑하려면 대체를 수행해야합니다.

  • "two signal"=> "두 스레드"/ "두 프로세스"
  • "출력에 영향을 미침"=> "일부 공유 상태에 영향을 미침"

따라서 소프트웨어 산업의 경쟁 조건은 "일부 공유 상태에 영향을 미치기"위해 서로 경쟁하는 "두 스레드"/ "두 프로세스"를 의미하며, 공유 상태의 최종 결과는 일부 미묘한 타이밍 차이에 따라 달라집니다. 스레드 / 프로세스 실행 순서, 스레드 / 프로세스 스케줄링 등


20

경쟁 조건은 동시 프로그래밍에서 두 개의 동시 스레드 또는 프로세스가 리소스를 놓고 경쟁하며 최종 최종 상태는 누가 리소스를 먼저 얻는 지에 따라 달라집니다.


훌륭한 설명
gokareless

무엇의 최종 상태?
로마 Alexandrovich

1
@RomanAlexandrovich 프로그램의 최종 상태. 변수 값 등과 같은 것을 언급하는 상태. Lehane의 탁월한 답변을 참조하십시오. 그의 예에서 "상태"는 'x'및 'y'의 최종 값을 나타냅니다.
AMTerp

19

경쟁 조건은 다중 스레드 응용 프로그램 또는 다중 프로세스 시스템에서 발생합니다. 경쟁 조건은 가장 기본적으로 동일한 스레드 또는 프로세스에없는 두 가지 작업이 특정 순서로 수행되며이를 수행하기위한 조치를 취하지 않는다고 가정하는 것입니다. 이것은 일반적으로 두 스레드가 클래스의 멤버 변수를 설정하고 확인하여 메시지를 전달할 때 발생합니다. 하나의 스레드가 작업을 완료하기 위해 다른 스레드에 시간을주기 위해 휴면을 호출 할 때는 거의 항상 경쟁 조건이 있습니다 (일부 점검 메커니즘을 사용하여 휴면 상태가 반복되지 않는 한).

경쟁 조건을 방지하기위한 도구는 언어 및 OS에 따라 다르지만 일부 comon 도구는 뮤텍스, 중요 섹션 및 신호입니다. 뮤텍스는 자신이 무언가를하는 유일한 사람인지 확인하고 싶을 때 좋습니다. 다른 사람이 무언가를 마쳤 으면 신호가 좋습니다. 공유 리소스를 최소화하면 예기치 않은 동작을 방지 할 수 있습니다

경쟁 조건을 감지하는 것은 어려울 수 있지만 몇 가지 징후가 있습니다. 수면에 크게 의존하는 코드는 경쟁 조건에 취약하기 때문에 먼저 영향을받는 코드에서 대기중인 통화를 확인하십시오. 특히 긴 대기 시간을 추가하면 특정 순서의 이벤트를 시도하고 강제로 디버깅하는 데 사용할 수 있습니다. 이는 동작을 재현하고, 타이밍을 변경하여 동작을 사라지게 할 수 있는지 확인하고, 솔루션을 테스트하는 데 유용합니다. 디버깅 후에는 절전 모드를 제거해야합니다.

경쟁 조건이있는 서명 부호는 일부 시스템에서 간헐적으로 만 발생하는 문제가있는 경우입니다. 일반적인 버그는 충돌 및 교착 상태입니다. 로깅을 사용하면 영향을받는 영역을 찾아서 다시 작업 할 수 있어야합니다.


10

Microsoft는 실제로이 경쟁 조건 및 교착 상태에 대한 자세한 기사 를 게시했습니다 . 그것에서 가장 요약 된 초록은 제목 단락입니다.

경쟁 조건은 두 스레드가 동시에 공유 변수에 액세스 할 때 발생합니다. 첫 번째 스레드는 변수를 읽고 두 번째 스레드는 변수에서 동일한 값을 읽습니다. 그런 다음 첫 번째 스레드와 두 번째 스레드는 값에 대한 작업을 수행하고 공유 변수에 마지막으로 값을 쓸 수있는 스레드를 찾기 위해 경쟁합니다. 스레드가 이전 스레드가 쓴 값을 덮어 쓰므로 마지막으로 값을 쓰는 스레드의 값이 유지됩니다.


5

경쟁 조건은 무엇입니까?

프로세스가 다른 이벤트의 순서 나 타이밍에 결정적으로 의존하는 상황.

예를 들어, 프로세서 A와 프로세서 B 모두 실행에 동일한 리소스가 필요 합니다.

당신은 그들을 어떻게 감지합니까?

경쟁 조건을 자동으로 감지하는 도구가 있습니다.

어떻게 처리합니까?

경쟁 조건은 Mutex 또는 Semaphores에 의해 처리 될 수 있습니다 . 잠금 역할을하여 프로세스가 경쟁 조건을 방지하기 위해 특정 요구 사항에 따라 리소스를 획득 할 수 있도록합니다.

그것들이 발생하는 것을 어떻게 방지합니까?

치명적 섹션 회피 와 같은 경쟁 조건을 방지하는 다양한 방법이 있습니다 .

  1. 중요한 영역 내에서 동시에 두 개의 프로세스가 없습니다. ( 상호 제외)
  2. 속도 나 CPU 수에 대한 가정은 없습니다.
  3. 다른 프로세스를 차단하는 중요한 영역 외부에서 실행중인 프로세스가 없습니다.
  4. 중요한 지역에 진입하기 위해 프로세스를 영원히 기다릴 필요는 없습니다. (A는 B 자원을 기다립니다. B는 C 자원을 기다립니다. C는 A 자원을 기다립니다)

2

경쟁 조건은 장치 또는 시스템이 동시에 둘 이상의 작업을 수행하려고 할 때 발생하는 바람직하지 않은 상황이지만 장치 또는 시스템의 특성으로 인해 작업을 수행하려면 적절한 순서로 수행해야합니다. 올바르게 완료되었습니다.

컴퓨터 메모리 또는 스토리지에서 대량의 데이터를 읽고 쓰는 명령이 거의 같은 순간에 수신되고 머신이 이전 데이터가 여전히있는 동안 이전 데이터의 일부 또는 전부를 덮어 쓰려고하면 경쟁 조건이 발생할 수 있습니다. 읽다. 결과는 컴퓨터 충돌, "잘못된 작업", 프로그램 알림 및 종료, 이전 데이터 읽기 오류 또는 새 데이터 쓰기 오류 중 하나 이상일 수 있습니다.


2

다음은 초보자가 Java의 스레드를 쉽게 이해하여 경쟁 조건을 쉽게 이해하는 데 도움이되는 고전적인 은행 계좌 잔액 예제입니다.

public class BankAccount {

/**
 * @param args
 */
int accountNumber;
double accountBalance;

public synchronized boolean Deposit(double amount){
    double newAccountBalance=0;
    if(amount<=0){
        return false;
    }
    else {
        newAccountBalance = accountBalance+amount;
        accountBalance=newAccountBalance;
        return true;
    }

}
public synchronized boolean Withdraw(double amount){
    double newAccountBalance=0;
    if(amount>accountBalance){
        return false;
    }
    else{
        newAccountBalance = accountBalance-amount;
        accountBalance=newAccountBalance;
        return true;
    }
}

public static void main(String[] args) {
    // TODO Auto-generated method stub
    BankAccount b = new BankAccount();
    b.accountBalance=2000;
    System.out.println(b.Withdraw(3000));

}

1

"원자"클래스를 사용하면 경쟁 조건을 방지 할 수 있습니다 . 그 이유는 스레드가 get 및 set 작업을 분리하지 않기 때문입니다.

AtomicInteger ai = new AtomicInteger(2);
ai.getAndAdd(5);

결과적으로 링크 "ai"에 7이 있습니다. 두 가지 작업을 수행했지만 두 작업 모두 동일한 스레드를 확인하고 다른 스레드가이를 방해하지 않으므로 경쟁 조건이 없습니다!


0

경쟁 조건에 대한 이해를 돕기 위해이 기본 예제를 사용해보십시오.

    public class ThreadRaceCondition {

    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        Account myAccount = new Account(22222222);

        // Expected deposit: 250
        for (int i = 0; i < 50; i++) {
            Transaction t = new Transaction(myAccount,
                    Transaction.TransactionType.DEPOSIT, 5.00);
            t.start();
        }

        // Expected withdrawal: 50
        for (int i = 0; i < 50; i++) {
            Transaction t = new Transaction(myAccount,
                    Transaction.TransactionType.WITHDRAW, 1.00);
            t.start();

        }

        // Temporary sleep to ensure all threads are completed. Don't use in
        // realworld :-)
        Thread.sleep(1000);
        // Expected account balance is 200
        System.out.println("Final Account Balance: "
                + myAccount.getAccountBalance());

    }

}

class Transaction extends Thread {

    public static enum TransactionType {
        DEPOSIT(1), WITHDRAW(2);

        private int value;

        private TransactionType(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }
    };

    private TransactionType transactionType;
    private Account account;
    private double amount;

    /*
     * If transactionType == 1, deposit else if transactionType == 2 withdraw
     */
    public Transaction(Account account, TransactionType transactionType,
            double amount) {
        this.transactionType = transactionType;
        this.account = account;
        this.amount = amount;
    }

    public void run() {
        switch (this.transactionType) {
        case DEPOSIT:
            deposit();
            printBalance();
            break;
        case WITHDRAW:
            withdraw();
            printBalance();
            break;
        default:
            System.out.println("NOT A VALID TRANSACTION");
        }
        ;
    }

    public void deposit() {
        this.account.deposit(this.amount);
    }

    public void withdraw() {
        this.account.withdraw(amount);
    }

    public void printBalance() {
        System.out.println(Thread.currentThread().getName()
                + " : TransactionType: " + this.transactionType + ", Amount: "
                + this.amount);
        System.out.println("Account Balance: "
                + this.account.getAccountBalance());
    }
}

class Account {
    private int accountNumber;
    private double accountBalance;

    public int getAccountNumber() {
        return accountNumber;
    }

    public double getAccountBalance() {
        return accountBalance;
    }

    public Account(int accountNumber) {
        this.accountNumber = accountNumber;
    }

    // If this method is not synchronized, you will see race condition on
    // Remove syncronized keyword to see race condition
    public synchronized boolean deposit(double amount) {
        if (amount < 0) {
            return false;
        } else {
            accountBalance = accountBalance + amount;
            return true;
        }
    }

    // If this method is not synchronized, you will see race condition on
    // Remove syncronized keyword to see race condition
    public synchronized boolean withdraw(double amount) {
        if (amount > accountBalance) {
            return false;
        } else {
            accountBalance = accountBalance - amount;
            return true;
        }
    }
}

0

경쟁 조건을 항상 버리고 싶지는 않습니다. 여러 스레드에서 읽고 쓸 수있는 플래그가 있고이 플래그가 한 스레드에 의해 '완료'로 설정되어 플래그가 '완료'로 설정된 경우 다른 스레드가 처리를 중지하도록하려면 "레이스"를 원하지 않습니다. 조건 "을 제거해야합니다. 실제로 이것은 양성 경쟁 조건이라고 할 수 있습니다.

그러나 경쟁 조건 감지 도구를 사용하면 유해한 경쟁 조건으로 간주됩니다.

경쟁 조건에 대한 자세한 내용은 여기 ( http://msdn.microsoft.com/en-us/magazine/cc546569.aspx)를 참조하십시오 .


귀하의 답변은 어떤 언어를 기반으로합니까?
MikeMB

솔직히 당신이 경쟁 조건이있는 경우 나에게 것 그 자체를 , 당신이 밀접하게 제어 된 방식으로 코드를 아키되지 않습니다. 이론적 인 경우에는 문제가되지 않지만 소프트웨어를 디자인하고 개발하는 방법에있어 더 큰 문제가 있다는 증거입니다. 조만간 고통스러운 경쟁 조건 버그에 직면 할 것으로 예상됩니다.
엔지니어

0

카운트가 증가하자마자 카운트를 표시해야하는 작업을 고려하십시오. 즉, CounterThread가 증가하는 즉시 DisplayThread 는 최근 업데이트 된 값을 표시해야합니다.

int i = 0;

산출

CounterThread -> i = 1  
DisplayThread -> i = 1  
CounterThread -> i = 2  
CounterThread -> i = 3  
CounterThread -> i = 4  
DisplayThread -> i = 4

여기서 CounterThread 는 잠금을 자주 받고 DisplayThread 가 표시 하기 전에 값을 업데이트 합니다. 경쟁 조건이 있습니다. 동기화를 사용하여 경쟁 조건을 해결할 수 있습니다


0

경쟁 조건은 둘 이상의 프로세스가 동시에 공유 데이터에 액세스하고 변경할 수있는 경우 바람직하지 않은 상황으로, 리소스에 대한 액세스가 충돌하여 발생했습니다. 치명적인 섹션 문제로 인해 경쟁 조건이 발생할 수 있습니다. 프로세스 중 중요한 조건을 해결하기 위해 중요 섹션을 실행하는 한 번에 하나의 프로세스 만 수행했습니다.

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