[JAVA|DB] 동시성과 공유 자원 🗂️ | 꼬이지 않게 관리하는 법

2025. 11. 13. 17:06·✏️공부/💡JAVA
728x90
반응형

동시성과 공유 자원 🗂️ | 꼬이지 않게 관리하는 법

서버가 동시에 여러 요청을 처리하다 보면, 하나의 데이터를 여러 스레드가 동시에 건드리는 상황이 생긴다.
이때 제대로 제어하지 않으면 데이터가 꼬이고, 예기치 못한 결과가 발생한다.
이 글에서는 그런 문제를 동시성과 공유 자원 관점에서 정리한다.


 

1️⃣ 동시성과 공유 자원의 문제

여러 스레드가 동시에 하나의 자원(변수, 객체, DB 레코드 등)에 접근할 때 문제가 생긴다.
이 현상을 Race Condition(경쟁 상태)이라고 한다.

 

예시

  • 두 스레드가 같은 카운터 값을 읽고 +1을 수행했지만, 실제로는 한 번만 증가되는 경우
  • 동시에 재고를 차감해 재고가 음수가 되는 경우

2️⃣ 왜 중요한가

웹 서버나 이벤트 시스템처럼 동시에 요청이 쏟아지는 환경에서는, 이런 문제가 데이터 무결성(integrity)을 직접적으로 깨뜨린다.

예를 들어 재고가 1인데 두 주문이 동시에 들어오면,

둘 다 성공하여 재고가 -1이 되거나 한쪽이 누락되는 문제가 생길 수 있다.

 


3️⃣ 원자성 / 가시성 / 배타성

동시성 제어는 세 가지 핵심 개념으로 구성된다.

  • 원자성(Atomicity)
    하나의 연산이 중간 상태 없이 완전히 수행되는 성질이다.
    `count++` 같은 단순 연산도 내부적으로 여러 단계이므로, 섞이면 오류가 생긴다.
  • 가시성(Visibility)
    한 스레드의 변경이 다른 스레드에서 즉시 보이도록 하는 성질이다.
    CPU 캐시나 메모리 동기화 지연으로 가시성이 깨질 수 있다.
  • 배타성(Mutual Exclusion)
    여러 스레드가 동시에 동일 자원에 접근하지 못하도록 막는 성질이다.

4️⃣ 해결 방법

  • synchronized / Lock
    특정 코드 블록에 한 스레드만 진입하게 하여 배타성을 확보한다.
  • volatile
    캐시를 무시하고 메인 메모리에서 직접 읽어 가시성을 보장한다.
    단, 복합 연산(읽기 → 수정 → 쓰기)은 보장하지 않는다.
  • Atomic 클래스 사용
    AtomicInteger, AtomicLong 등을 사용하면 CAS 기반으로 원자성을 보장한다.
  • DB 수준의 락 활용
    비관적 락, 낙관적 락 등 DB 차원의 제어를 함께 고려한다.

5️⃣ Java에서 자주 쓰는 동시성 제어 기법

기법 특징
`synchronized` 간단하지만 JVM 내부에서만 유효하다.
`Lock / ReentrantLock` 세밀한 제어가 가능하다.
`volatile` 가시성만 보장하며 복합 연산은 불가능하다.
`AtomicXxx` (다양한 시리즈) 락 없이 원자적 연산을 수행한다.
`DB 락 / 분산 락` 여러 서버 간 자원 제어를 위해 필요하다.

 


6️⃣ 애플리케이션 vs DB vs 분산 환경

  • 애플리케이션 락은 간단하지만 단일 서버에서만 유효하다.
  • DB 락은 트랜잭션 격리 수준을 활용해 레코드 단위의 제어가 가능하다.
  • 분산 락은 Redis나 Zookeeper를 통해 여러 서버 간 동시성을 제어한다.

환경이 단일인지, 다중 서버인지에 따라 접근 방식이 달라야 한다.


⚠️ 주의할 점

  • `@Transactional`과 `synchronized`를 함께 사용하면 예상치 못한 동작이 발생할 수 있다.
  • 락을 과도하게 사용하면 병목이 생긴다.
  • 가능한 공유 상태를 줄이고 불변 객체를 활용하는 것이 좋다.

7️⃣ 정리

동시성 제어는 코드 한 줄로 끝나는 문제가 아니다.
원자성, 가시성, 배타성을 이해하고, 환경(단일/분산)과 데이터 특성을 고려해야 안정적인 시스템이 만들어진다.

 

 

728x90
반응형

'✏️공부 > 💡JAVA' 카테고리의 다른 글

[JAVA] Record 🎥 | Record를 DTO로 사용하는 이유  (0) 2025.11.24
[JAVA] Lombok & Validation 정리 | 필수 어노테이션 가이드 📖 | @Getter / @Setter | @NoArgsConstructor / @AllArgsConstructor / @RequiredArgsConstructor  (0) 2025.09.21
[JAVA] ⚙️ 자료구조 : Heap | 간단 정리 및 삽입•삭제 과정 💬  (5) 2025.08.21
[JAVA] ⚙️ 자료구조 : Tree & Binary Search Tree 🌲 | 트리 순회 | 간단 정리 및 비교 💬  (0) 2025.08.21
[JAVA] ⚙️ 자료 구조 : Stack / Queue / Deque | 간단 비교 및 정리 💬  (0) 2025.08.21
'✏️공부/💡JAVA' 카테고리의 다른 글
  • [JAVA] Record 🎥 | Record를 DTO로 사용하는 이유
  • [JAVA] Lombok & Validation 정리 | 필수 어노테이션 가이드 📖 | @Getter / @Setter | @NoArgsConstructor / @AllArgsConstructor / @RequiredArgsConstructor
  • [JAVA] ⚙️ 자료구조 : Heap | 간단 정리 및 삽입•삭제 과정 💬
  • [JAVA] ⚙️ 자료구조 : Tree & Binary Search Tree 🌲 | 트리 순회 | 간단 정리 및 비교 💬
망꼬누나
망꼬누나
공부한 내용을 정리하는 공간입니다.
  • 망꼬누나
    망꼬누나의 개발 공부
    망꼬누나
  • 전체
    오늘
    어제
    • 분류 전체보기 (165)
      • ℹ️ 정보 및 실습 (19)
        • ☑️ Git & GitHub (8)
        • ☑️ 프로젝트 (6)
        • ☑️ 회고 및 후기 (5)
      • 🛠 CS (1)
      • 💻코딩 (88)
        • 💡Baekjoon (17)
        • 💡Programmers (71)
      • ✏️공부 (48)
        • 💡OS (1)
        • 💡Network (6)
        • 💡SpringBoot (9)
        • 💡JAVA (21)
        • 💡SQL (1)
        • 💡DB (2)
        • ☁️ Cloud (4)
        • 💡알고리즘 (4)
      • 📌 자격증 (6)
        • 📝정보처리기사 (3)
        • 📝SQLD (3)
  • 블로그 메뉴

    • 홈
    • github
  • 나의 GitHub Contribution 그래프
    Loading data ...
  • 인기 글

  • 태그

    github
    Java
    프로그래머스 #JAVA
    Stream
    백엔드
    자료구조
    baekjoon
    동시성제어
    자바
    AWS
    알고리즘
    프로그래머스
    네트워크
    map
    GIT
    코딩테스트
    트랜잭션
    데브코스
    S3
    Set
  • 최근 댓글

  • 최근 글

  • 250x250
    반응형
  • hELLO· Designed By정상우.v4.10.5
망꼬누나
[JAVA|DB] 동시성과 공유 자원 🗂️ | 꼬이지 않게 관리하는 법
상단으로

티스토리툴바