Java에서의 동시성 관련 키워드

참고 링크

Books

Brian Goetz, Tim Peierls, Bloch Joshua, Bowbeer Joseph, Holmes David, Lea Doug (2006). Java Concurrency in Practice. Addison-Wesley Professional.

Joshua Bloch(2018). Effective Java(3rd ed.). Addison-Wesley Professional.

Lectures

스프링 핵심 원리 - 고급편

재고시스템으로 알아보는 동시성이슈 해결방법

Articles

🔒 Java 로 동기화를 해보자!

Posts

[Study] 동시성(Concurrency) 과 병렬성 (Parallelism) 올바른 개념 잡기

메모리와, 연속 메모리 할당(contiguous memory allocation)

[Java] 멀티 스레드환경의 동시성 이슈 그리고 해결방법

자바 백엔드 기술 면접 대비하기 - 1편

[Java] Java의 동시성 이슈

[Java] Concurrent Programming - 가시성과 원자성


이번 글에서는 아래 정리한 순서에 따라 Java와 동시성 키워드 에 관련된 여러 가지 주제들을 다뤄보려고 합니다.


- 동시성 문제
    - 동기화
    - 동시성과 병렬성
- synchronized - 암시적 Lock
    - wait(), notify(), notifyAll()
    - 동시성 유틸리티(실행자 프레임워크, 동시성 컬렉션, 동기화 장치)
- java.util.concurrent.locks - 명시적 Lock
    - ReentrantLock
        - Condition
    - ReentrantReadWriteLock
    - StampedLock
- Atomic Type
- volatile
    - 가시성과 원자성
- ThreadLocal


동시성 문제와 관련된 키워드

프로세스 동기화


멀티 스레드와 동기화


병렬성(Parallelism)과 동시성(Concurrency)

image

병렬성

image

동시성


동시성 문제

동시성 문제 예제

image

🤔 100개 수량이 있는 재고를 하나씩 감소 시키는 어떤 요청이 있을 때 해당 요청을 100개를 실행하는데 이 때 멀티 스레드로 요청을 수행한다면 결과가 어떻게 될까요?

image




Java의 동기화 키워드 - synchronized

사용 방법

1) synchronized methods: 메소드 자체를 synchronized로 선언해서 사용합니다.

image

2) synchronized statements: 메소드 내의 특정 문장만 synchronzied로 감싸는 방법입니다.

image

synchronized의 주의점

사용 예제

🤔 100개 수량이 있는 재고를 하나씩 감소시키는 요청 100개를 멀티스레드로 수행한다면? (위 동기화 문제 예제 동일)

image

image

image

image


스레드 상태 제어 메서드 - wait(), notify(), notifyAll()

image


참고 - 동시성 유틸리티

Effective Java Item 81. wait와 notify보다는 동시성 유틸리티를 애용해라

1) 실행자 프레임워크

// 작업 큐 생성
ExecutorService exec = Executors.newSingleThreadExecutor();

// 실행할 태스크 넘기기
exec.execute(runnable);

// 실행자 종료
exec.shutdown();

2) 동시성 컬렉션(concurrent collection)

3) 동기화 장치(synchronizer)




Java의 동기화 키워드 - java.util.concurrent.lock 명시적 Lock

ReentrantLock: 재진입이 가능한 Lock이고 가장 일반적인 Lock

image


cf.) Condition

image


ReentrantReadWriteLock: 읽기 & 쓰기를 위한 Lock

image

image

image

image


StampedLock: 락을 걸거나 해지할 때 ‘스탬프(long 타입의 정수 값)’를 사용

image




Java의 동기화 키워드 - Atomic Type (concurrent package 사용)

사용 방법




Java의 동기화 키워드 - volatile

Volatile 가시성?


volatile 사용 전

image

image


volatile 사용 후

image

image


🤔 Volatile은 어떤 상황에 사용할까요?


🤔 그렇다면 가시성이 보장되면 동시성도 보장될까요?

cf.) 가시성 vs 원자성

❓ Ex. Q. 0이 들어있는 변수(i)에 10개의 스레드가 동시에 접근해서 i++ 연산을 하면 우리 예상과 다르게 10이 나오지 않습니다. 왜 그럴까요?




Thread Local

Thread Local이 없을 때 발생할 수 있는 문제

image


  1. Thread-A 는 userA 를 nameStore 에 저장
  2. Thread-B 는 userB 를 nameStore 에 저장
  3. Thread-A 는 userB 를 nameStore 에서 조회
  4. Thread-B 는 userB 를 nameStore 에서 조회

=> 동시성 문제: Thread-A 입장에서는 저장한 데이터와 조회한 데이터가 다른 문제가 발생할 수 있습니다.


Thread Local을 적용하면?

image

🤔 Thread Local 사용 시 주의할 점은?

image

사용자A 저장 요청

  1. 사용자A가 저장 HTTP 요청
  2. WAS가 스레드풀에서 스레드를 하나 조회
  3. 스레드A 할당
  4. 스레드A가 사용자A의 데이터를 스레드 로컬에 저장
  5. 스레드 로컬의 스레드A 전용 보관소에 사용자A 데이터 보관


image

사용자A 저장 요청 종료

  1. HTTP 응답 종료
  2. WAS는 사용 끝난 스레드A를 스레드 풀에 반환(추후 스레드 재사용)
  3. 현재 스레드A는 스레드풀에 재사용을 위해 살아있고 스레드 로컬의 스레드A 전용 보관소의 사용자 A의 데이터 역시 살아있음


사용자 B 조회 요청

image

  1. 사용자B가 조회를 위해 새로운 HTTP 요청
  2. WAS가 스레드풀에서 스레드를 조회
  3. 스레드A 할당(다른 스레드가 할당될 수도 있음)
  4. 스레드A가 스레드 로컬에서 데이터 조회
  5. 스레드 로컬이 스레드A 전용 보관소에 있는 사용자A 값 반환
  6. 사용자A 값이 사용자B에게 전달
  7. 의도치 않은 값으로 사용자B에게 응답