"Race condition"이란 컴퓨터 과학과 소프트웨어 엔지니어링에서 발생하는 문제로, 시스템의 출력이 특정 순서나 타이밍에 의존할 때 발생합니다. 이는 병렬 처리나 동시성을 다루는 시스템에서 흔히 볼 수 있는 현상
상황: 은행 계좌에 100달러가 있고, 두 개의 다른 트랜잭션이 동시에 발생합니다.
정의: 여러 스레드가 데이터를 공유할 때, 그 데이터에 접근하는 코드의 일부분을 '임계 구역'이라고 합니다. 한 스레드가 임계 구역에 있는 동안 다른 스레드는 그 구역에 접근해서는 안 됩니다.
중요성: 임계 구역 관리는 데이터의 일관성과 무결성을 유지하는 데 필수적입니다. 잘못 관리되면 데이터 충돌, race condition 등의 문제가 발생할 수 있습니다.
정의: 상호 배제는 한 번에 하나의 스레드만이 특정 임계 구역에 접근할 수 있도록 보장하는 개념입니다.
목적: 이는 여러 스레드가 동시에 공유 데이터에 접근하는 것을 방지하여 데이터의 일관성을 유지하는 데 중요합니다.
Mutex는 Mutual Exclusion(상호 배제)의 약어로, 한 번에 하나의 스레드 또는 프로세스만 공유 자원에 접근할 수 있도록 하는 동기화 기법입니다.
뮤텍스는 주로 크리티컬 섹션(Critical Section)에 접근하는 스레드 간의 경쟁 조건을 방지하는 데 사용됩니다.
뮤텍스는 잠금(lock)과 해제(unlock) 연산을 사용하여 공유 자원의 접근을 제어합니다.
세마포어는 여러 스레드 또는 프로세스가 공유 자원에 접근할 수 있는 허용된 수를 나타내는 카운터입니다. 이 카운터는 양수일 수도 있고 음수일 수도 있습니다.
세마포어는 일반적으로 "이진 세마포어(Binary Semaphore)"와 "카운팅 세마포어(Counting Semaphore)" 두 가지 종류로 나뉩니다.
세마포어는 wait(대기)과 signal(신호) 연산을 사용하여 공유 자원의 접근을 제어합니다.
자바에서는 여러 가지 방법으로 임계 구역과 상호 배제를 구현할 수 있습니다:
메소드 전체 또는 특정 코드 블록에 synchronized 키워드를 사용합니다.
이 방법은 해당 메소드/블록에 대한 접근을 동기화하여 한 번에 하나의 스레드만 접근할 수 있도록 합니다.
java.util.concurrent.locks 패키지의 Lock 인터페이스를 사용할 수 있습니다.
ReentrantLock 클래스는 가장 일반적으로 사용되는 Lock 구현입니다.
명시적인 lock과 unlock 메소드를 제공하여 세밀한 제어가 가능합니다.
java.util.concurrent.atomic 패키지에 있는 클래스들은 원자적 연산을 지원합니다.
이러한 변수들은 race condition 없이 하나의 스레드에 의해 안전하게 읽고 쓸 수 있습니다.
변수에 volatile 키워드를 사용하면 모든 스레드에 변수의 최신 값을 보장합니다.
이는 변수의 가시성을 보장하지만, 복합 연산에 대해서는 상호 배제를 보장하지 않습니다.