개념부터 살펴보면 레이스 컨디션은 두 개 이상의 프로세스 혹은 스레드가 공유 자원을 서로 사용하려고 경합(Race)하는 현상을 의미한다.
Java에서 애플리케이션 개발을 진행하다 보면 Multi Thread를 활용한 프로그래밍을 경험하게 된다.(스프링은 기본적으로 멀티스레드 환경에서 동작합니다. )
서로 다른 실행흐름에서 자원에 동시에 접근하면 원하지 않는 결과를 얻을 수 있다. 아래 이미지 참조.
public class RaceConditionExample {
private int counter = 0;
public void increment() {
counter++;
}
public int getCounter() {
return counter;
}
public static void main(String[] args) {
RaceConditionExample example = new RaceConditionExample();
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
};
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final counter value: " + example.getCounter());
}
}
프로세스: 메모리에 올라가서 실행 중인 프로그램을 의미하며, 독립된 실행 환경을 가집니다. 각 프로세스는 별도의 메모리 공간을 할당받습니다.
스레드: 프로세스 내에서 실행 흐름을 의미합니다. 하나의 프로세스에는 하나 이상의 스레드가 있을 수 있으며, 각 스레드는 같은 프로세스 내에서 메모리 공간을 공유합니다.
멀티스레드: 하나의 프로세스가 여러 스레드를 가지고 있으며, 각각의 스레드가 동시에 실행 흐름을 처리하는 구조입니다. 이는 동시에 여러 작업을 수행할 수 있게 하여 프로그램 성능을 향상시키는 데 도움을 줍니다.
공유 자원에 접근하는 코드 영역을 의미하며, 이 영역은 여러 스레드가 동시에 접근하면 문제가 발생할 수 있습니다.
예를 들어, 두 개 이상의 스레드가 동일한 데이터를 동시에 읽고 수정하려고 할 때, 이로 인해 예상하지 못한 결과나 데이터 불일치가 발생할 수 있습니다.
이러한 문제를 방지하기 위해 임계영역에서는 동기화(Syncronized)가 필요합니다.
레이스 컨디션 해결 방법 구체화
레이스 컨디션을 해결하기 위한 다양한 방법들을 소개하면 더 좋습니다. 예를 들어, synchronized, Lock, Atomic 클래스 등을 비교 설명할 수 있습니다.
synchronized 키워드: Java에서 가장 기본적인 방법으로, 한 번에 하나의 스레드만 임계영역에 진입할 수 있도록 함.
public synchronized void increment() {
counter++;
}
synchronized, Lock, 뮤텍스, 세마포어도 고려해보자!
https://velog.io/@squarebird/%EB%A0%88%EC%9D%B4%EC%8A%A4-%EC%BB%A8%EB%94%94%EC%85%98
https://velog.io/@maketheworldwise/%EB%A0%88%EC%9D%B4%EC%8A%A4-%EC%BB%A8%EB%94%94%EC%85%98-%EA%B7%B8%EA%B2%8C-%EB%AD%90%EC%95%BC