동시성 이슈

Yuno·2024년 8월 13일
0

JavaSpring

목록 보기
14/16

✏️ 동시성 이슈란?

여러 프로세스나 스레드가 동시에 리소스를 접근하려 할 때 발생하는 문제.
데이터베이스, 파일 시스템, 메모리 등 다양한 리소스에서 동시성 이슈가 발생할 수 있으며, 이는 데이터 무결성 문제, 성능 저하, 프로그램 크래시 등을 초래할 수 있음

프로세스 : 실행 중인 프로그램의 인스턴스를 의미
스레드 : 프로세스 내에서 실행되는 흐름의 단위
프로그램 크래시 : 프로그램이 예상치 못한 이유로 강제로 종료되거나 응답하지 않는 상태를 의미

😱 동시성 이슈의 주요 원인

  1. 경쟁 상태(Race Condition) : 두 개 이상의 스레드가 동시에 동일한 리소스에 접근하고 수정할 때 발생. 결과는 스레드의 실행 순서에 따라 달라질 수 있음
  2. 데드락(Deadlock) : 두 개 이상의 프로세스나 스레드가 서로가 가진 리소스를 기다리면서 무한 대기 상태에 빠지는 상황
  3. 라이브락(Livelock) : 프로세스나 스레드가 계속해서 상태를 변경하지만 실질적으로 진전을 이루지 못하는 상황
  4. 스타베이션(Starvation) : 특정 스레드나 프로세스가 필요한 리소스를 얻지 못해 계속 대기 상태에 있는 상황

😮 동시성 문제를 해결하는 방법

  1. 동기화(Synchronization)
  • 뮤텍스(Mutex) : 상호 배제(mutual exclusion) 기법으로, 한 번에 하나의 스레드만 리소스에 접근할수 있도록 보장
  • 세마포어(Semaphore) : 제한된 수의 스레드만 리소스에 접근할 수 있도록 제어
  • 자바의 synchronized 키워드 : 특정 코드 블록이 동시에 하나의 스레드만 접근하도록 함
public synchronized void synchronizedMethod() {
	// 동기화된 코드
}
  • Lock 객체 : 자바의 java.util.concurrent.locks 패키지에 있는 Lock 인터페이스를 사용하여 동기화를 구현
Lock lock = new ReentrantLock();
lock.lock();
try {
	// 동기화된 코드
} finally {
	lock.unlock();
}
  1. 원자성(Atomicity)
  • 원자적 연산 : 원자적 연산을 사용하여 여러 스레드가 동시에 변경해도 일관성을 유지할 수 있도록 함
    자바의 AtomicInteger, AtomicLong 등의 클래스를 사용할 수 있음
AtomicInteger counter = new AtomicInteger();
counter.incrementAndGet();
  1. 교착 상태 방지(Deadlock Prevention)
  • 자원 할당 순서 : 자원 할당의 순서를 정의하고, 항상 동일한 순서로 자원을 요청하도록 함
  • 타임아웃 : 자원 요청에 타임아웃을 설정하여, 일정 시간이 지나면 자원 요청을 포기하도록 함
  1. 동시성 제어(Concurrency Control)
  • 낙관적 잠금(Optimistic Locking) : 데이터베이스에서 특정 레코드를 수정하기 전에 데이터가 변경되지 않았는지 확인. 버전 번호를 사용하는 방법이 있음
  • 비관적 잠금(Pessimistic Locking) : 데이터를 수정하기 전에 데이터베이스에서 잠금을 획득하여 다른 트랜잭션이 접근하지 못하도록 함
SELECT * FROM table_name WHERE condition FOR UPDATE;
  1. 스레드 안전성(Thread Safety)
  • 불변 객체 : 객체의 상태를 변경할 수 없도록 하여 스레드 안전성을 보장
  • 불변 컬렉션 : 자바의 Collections.unmodifiableList 와 같은 불변 컬렉션을 사용
  1. 테스트 및 모니터링
  • 경쟁 상태 테스트 : 다양한 테스트 도구와 기법을 사용하여 경쟁 상태를 검출. JUnit과 같은 테스트 프레임워크와 함께 동시성 테스트 도구를 사용할 수 있음
  • 프로파일링 및 모니터링 : 애플리케이션의 동시성 문제를 발견하고 해결하기 위해 프로파일링 및 모니터링 도구를 사용

자바에서 동기화 사용하기

public class Counter {
	private int count = 0;
    
    // 동기화된 메서드
    public synchronized void increment() {
    	count++;
    }
    
    public synchronized int getCoint() {
    	return count;
    }
}

incrementgetCount 메서드가 동기화 되어, 동시에 여러 스레드가 접근할 때도 데이터의 일관성을 유지할 수 있음

profile
Hello World

0개의 댓글