김영한의 실전 자바 - 고급 1편(CAS)

2025. 1. 11. 22:47·김영한의 실전 자바 - 고급 1편

원자적 연산이란 무엇인가? i++; 은 원자적 연산인가?

  • 원자적 연산의 의미는 해당 연신이 더 이상 나눌 수 없는 단위로 수행된다는 것을 의미
  • 예를 들어서 i = 1 은 원자적 연산이다.
  • i ++ (i = i + 1 )은 원자적 연산이 아니며 다음과 같이 세 파트로 나눠질 수 있다.
    • 오른쪽에 있는 i의 값을 읽는다
    • 읽은 i의 값에 1을 더한다.
    • 더해진 값을 왼쪽 i에 대입한다.

 

원자적 연산과 동시성 문제의 상관 관계에 대해 설명하시오

  • 원자적 연산일 경우 동시성 문제가 발생하지 않고, 그렇지 않을 경우 동시성 문제가 발생한다.
  •  i = i + 1의 경우를 예로 들어보자. (i의 기존 값이 10이라고 가정하자)
  • 1. 오른쪽 i의 조회된 값은 10이다.
  • 2. 조회된 10에 1을 더한다.
  • 3. 그 이후 11을 왼쪽 i에 대입한다.
  • 하지만 다른 스레드에서 이미 1번 이후에 i의 값을 12로 바꿨으면, 이 작업은 사실 i에서 1을 더한 13이 되야 하므로 동시성 문제가 발생한 케이스라고 할 수 있다.

 

위 i = i + 1 은 원자적 연산이 아니라 동시성 문제를 해결하려면 Lock을 걸어서 해결해야하지만 Lock을 걸지 않고도 동시성 문제를 해결할 수 있는 방법이 있다. 그 방법에 대해 자세히 설명하시오

 

  • 그 방법은, CAS(CompareAnd-Swap, Compare-And-Set) 연산이다.
  • 락을 걸지 않아도 되는 이유는 그 여러 작업에 대한 연산을 하드웨어 단에서 동시에 처리가 가능하기 때문.
  • CPU에서 메인메모리에 있는 값을 읽고, 그 값이 우리가 조회한 값이 맞다면 우리가 원하는 값으로 변경한다.
  • 조회 및 변경이므로 원자적 연산이 아니지만, 하드웨어단에서 이걸 원자적으로 처리하는 기능을 제공함.

 

CAS와 Lock 방식의 장단점을 설명하시오

비교 요약 표

비교 항목  Lock 방식  CAS 방식
접근 철학 비관적 접근 (Pessimistic) 낙관적 접근 (Optimistic)
락 사용 여부 사용 사용하지 않음
데이터 접근 방식 락 획득 후 접근 충돌 발생 시 재시도
성능 스레드 경쟁 시 성능 저하 충돌이 적을 때 높은 성능
안전성 높은 일관성 보장 충돌 발생 시 재시도 필요
적용 사례 스레드 경쟁이 많을 때 유리 충돌이 적을 때 유리
  • Lock 방식은 매번 Lock을 걸고 Runnable -> Waiting -> Runnable 로 상태 변환, Context Swtiching이 일어나야 하므로 성능 저하가 발생할 수 있음.
  • 반면에, CAS는 Lock 과정이 없이 하드웨어단에서 처리되므로 성능이 훨씬 높음.
  • 문제는, CAS 방식은 하드웨어단에서 값을 조회 후 값이 맞다면 값을 변경하기 때문에, 너무 많은 쓰레드가 동시에 작업을 한다면 값을 조회 후 값이 틀린 경우에 계속 다시 시도해서 성능이 떨어질 가능성이 있음.
  • 따라서, 스레드간 경쟁이 너무 심한 경우는 Lock 방식이 더 나을 수도 있음.
  • 하지만 하드웨어의 연산은 1초에도 수십억건을 할 만큼 충돌이 생각보다 잘 나지 않기 때문에 실무단에서는 사실상 충돌이 그렇게 많은 경우는 적다고 판단 가능함.

'김영한의 실전 자바 - 고급 1편' 카테고리의 다른 글

김영한의 실전 자바 - 고급 1편(Executor)  (0) 2025.01.13
김영한의 실전 자바 - 고급 1편(동시성 컬렉션)  (0) 2025.01.11
김영한의 실전 자바 - 고급 1편(생산자 소비자 문제: Object - wait/notify, ReentarantLock - await/signal, BlockingQueue)  (1) 2025.01.08
김영한의 실전 자바 - 고급 1편(volatile, synchronized, LockSupport, ReentrantLock)  (1) 2025.01.05
김영한의 실전 자바 - 고급 1편(스레드 생명주기, join, interrupt, yield)  (2) 2025.01.04
'김영한의 실전 자바 - 고급 1편' 카테고리의 다른 글
  • 김영한의 실전 자바 - 고급 1편(Executor)
  • 김영한의 실전 자바 - 고급 1편(동시성 컬렉션)
  • 김영한의 실전 자바 - 고급 1편(생산자 소비자 문제: Object - wait/notify, ReentarantLock - await/signal, BlockingQueue)
  • 김영한의 실전 자바 - 고급 1편(volatile, synchronized, LockSupport, ReentrantLock)
5jyan5
5jyan5
  • 5jyan5
    jyan
    5jyan5
  • 전체
    오늘
    어제
    • 분류 전체보기 (242)
      • 김영한의 스프링 핵심 원리(기본편) (8)
      • 김영한의 스프링 핵심 원리 - 고급편 (11)
      • 김영한의 스프링 MVC 1편 (1)
      • 김영한의 스프링 DB 1편 (3)
      • 김영한의 스프링 MVC 2편 (3)
      • 김영한의 ORM 표준 JPA 프로그래밍(기본편) (9)
      • 김영한의 스프링 부트와 JPA 활용2 (2)
      • 김영한의 실전 자바 - 중급 1편 (1)
      • 김영한의 실전 자바 - 고급 1편 (9)
      • 김영한의 실전 자바 - 고급 2편 (9)
      • Readable Code: 읽기 좋은 코드를 작성.. (2)
      • 김영한의 실전 자바 - 고급 3편 (9)
      • CKA (118)
      • 개발 (37)
      • 경제 (4)
      • 리뷰 (1)
      • 정보 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      requset scope
      프록시
      @within
      WAS
      버퍼
      고급
      빈 후처리기
      jdk 동적 프록시
      cglib
      페치 조인
      JPQL
      reentarantlock
      Thread
      락
      Target
      hibernate5module
      @args
      김영한
      스레드
      typequery
      log trace
      자바
      단방향 맵핑
      gesingleresult
      @discriminatorvalue
      jpq
      조회 성능 최적화
      프록시 팩토리
      @discriminatorcolumn
      양방향 맵핑
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    5jyan5
    김영한의 실전 자바 - 고급 1편(CAS)
    상단으로

    티스토리툴바