[CS] Race condition이란?

Arthur·2023년 8월 7일
0
post-thumbnail

작성하게 된 계기


Race condition은 컴퓨터 공학 책을 공부하면 꼭 나오는 키워드입니다.
저도 컴퓨터 공학 기초 관련 서적을 읽으면서 한 번 이상은 접했었습니다.

어느정도 이해했다고 자기 최면에 빠진 상태로 넘어갔었는데,
이번에 면접 스터디를 통해 다양한 질문을 받아 보니 단순한 정의만 이해하고 있다는 것을 알게되었습니다.



Race condition이란?


둘 이상의 입력 또는 조작의 타이밍이나 순서 등이 결과값에 영향을 줄 수 있는 상태
<위키피디아 - 경쟁 상태>

Race condition은 공유(공통) 자원을 둘 이상의 스레드 혹은 프로세스가 읽거나 쓰면서 결과값이 의도와 달라질 수 있는 문제입니다.


Race condition의 문제점

  • 예측 불가능한 결과
    • 여러 스레드나 프로세스마다 실행 속도가 달라서 잘못된 값을 읽거나 수정할 수 있다.
    • A스레드가 수정 한 결과를 B가 수정하면서 A가 수정한 결과는 없어지게 된다.
  • 일관성 손실
    • 여러 스레드나 프로세스가 데이터를 수정 시 예기치 않은 상태로 데이터가 변경될 수 있다.
  • 디버깅의 어려움
    • 여러 스레드나 프로세스의 각각 다른 실행 속도로 인해 실행 흐름을 읽기 힘들어 디버깅이 힘듭니다.
  • 잠금 대기 시간
    • Race condition을 방지하기 위해 무분별한 락(Lock)을 사용할 시, 대기 시간으로 인해 성능 저하가 발생할 수 있습니다.

멀티 스레드에서의 공유 영역에는 대표적으로 데이터 영역과 힙 영역이 있습니다.
반대로 공유하지 않는 영역은 스택 영역입니다.

멀티 스레드 프로그래밍의 장점은 공유 영역을 여러 일들을 병렬로 처리 할 수 있는 것도 있지만,
자원을 공유하면서 생성과 관리의 중복성을 최소화 할 수 있는 장점도 있습니다.
하지만 이런 공유 영역이 양날의 검처럼 문제도 발생 할 위험이 있는 것입니다.

개념보다는 문제점을 직접 나열해보니 Race condition을 알아야 하는 이유가 좀 더 명확해지고,
멀티 스레드 프로그래밍이 어렵다고 하는 이유를 좀 더 알게 되는 것 같습니다.

그렇다면 Race condition을 예방하는 방법에는 무엇이 있을지 찾아봤습니다.



Race condition을 예방하는 방법


  • 상호 배제(Mutual Exclusion)
    • 공유 데이터에 접근하는 부분을 임계 영역(Critical Section)으로 지정하고, 한 번에 하나의 실행 흐름만 해당 영역에 들어가도록 한다.
  • 공유 데이터를 최소화한 병렬 처리 설계
    • 데이터를 적절히 분리하여 각 스레드가 독립적으로 처리하도록 합니다.
  • 스레드 안전성 보장(Thread Safe)
    • 공유 데이터를 수정하는 함수나 메서드를 스레드 안전하도록 구현
    • 이를 위해 스레드 동기화 기법을 사용하거나 불변 객체(Immutable Object)패턴 적용
  • 테스트와 검증
    • 코드를 작성 후 테스트를 진행합니다.
    • 테스트 코드를 작성해서 원하는 결과가 나오는지 확인합니다.

최대한 글을 요약해 봤지만, 각 키워드마다 거의 블로그 글 한 개 이상은 나오는 주제입니다.

상호 배제에 대해서는 이 글에서 작성할 예정이지만,
다른 해결 방법에 대해서 궁금하신 분들은 아래의 블로그 링크에 잘 작성되어 있습니다.

관심이 있으신 분들은 한 번 읽어 보시는 것을 추천드립니다.

  • 자바 병렬 프로그래밍 - 스레드 안전성(Thread Safe) (2) => 링크
  • [C#] Thread Safety 쓰레드 안전이란? => 링크


상호 배제(Mutual Exclusion, Mutex)


동시 프로그래밍에서 공유 불가능한 자원의 동시 사용을 피하기 위해 사용되는 알고리즘으로, 임계 구역(critical section)으로 불리는 코드 영역에 의해 구현된다.
<위키피디아 - 상호 배제>

  • 공유된 자원의 데이터를 여러 스레드가 접근하는 것을 막는 방법
  • 공유된 자원은 한 번에 한 프로세스(스레드)만이 사용할 수 있어야 한다.
  • key에 해당하는 어떤 오브젝트가 있으며 이 오브젝트를 소유한 (쓰레드, 프로세스) 만이 공유자원에 접근할 수 있다.

흔히 뮤텍스는 키(열쇠)가 하나뿐인 화장실을 예로 들어서 설명합니다.

화장실을 이용하기 위해서는 열쇠를 카운터에서 받아 가야 하고,
누군가 화장실 키를 가지고 사용하고 있으면 다른 사람들은 카운터에서 기다려야(대기) 합니다.

화장실을 이용하는 사람은 프로세스 혹은 스레드이며 화장실은 공유자원, 화장실 키는 공유자원에 접근하기 위해 필요한 어떤 오브젝트이다.

상호 배제에 대해서는 어느정도 이해를 했습니다.
그런데 위키피디아에 나오는 임계 구역이라는 것은 무엇을 의미하는지 궁금해서 찾아봤습니다.


임계 구역(Critical Section)이란?

공유변수 영역은 병렬컴퓨팅에서 둘 이상의 스레드가 동시에 접근해서 안되는 공유 자원(자료 구조 또는 장치)을 접근하는 코드의 일부를 말한다.
<위키피디아 - 임계 구역>

간단하게 정리하면 병렬 컴퓨팅과 멀티스레드 프로그래밍에서 상호 배제를 적용하는 부분을 가리키는 용어입니다.

임계 구을 효과적으로 사용하는 것은 Race condition과 같은 동시성 문제를 해결하기 위해 중요합니다.

이런 임계 구역에 접근하기 전에 락(Lock)이나 세마포어(Semaphore)와 같은 동기화 메커니즘을 사용하여 한 번에 하나의 실행 흐름만이 임계구역에 들어갈 수 있도록 합니다.

임계 구역을 제대로 알고 Race condition을 예방하면,
데이터의 일관성과 안전한 동시성 프로그래밍을 보장하는데 중요한 역할을 합니다.



작성하면서 느낀 점


CS 공부를 하면서 나오는 키워드를 한 번 읽어보고 넘어갔었습니다.

그런데 문제는 이런 각 키워드가 서로 연결성이 있는데,
그것을 못하고 그냥 개념만 이해할려고 하니까 제대로 이해를 못하는 문제가 발생했습니다.

이런 문제를 글로 작성하면서 꽤 도움이 된다는 것을 알게 되었습니다.

참고자료


  • 블로그 IRE Days - [운영체제] Race Condition과 예방할 방법(세마포어, 뮤텍스) => 링크
  • Baeldung - What Is a Race Condition? => 링크
  • 멀티 쓰레드(Multi Thread)란 무엇인가? => 링크
  • 뮤텍스와 세마포어 => 링크
  • 뮤텍스(Mutex)와 세마포어(Semaphore)의 차이 => 링크
  • process synchronization : 임계구역 (critical section) & 경쟁상태 (race condition) 링크
  • chatGPT
profile
기술에 대한 고민과 배운 것을 회고하는 게임 서버 개발자의 블로그입니다.

0개의 댓글