• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

synchronized 와 @Transactional

23.05.29 17:05 작성 조회수 750

0

안녕하세요 재고관리시스템 강의를 복습하며 내용을 정리하는 중 의문이 생겨 질문을 드립니다.

 

가장 처음에 application code 레벨에서만 동시성을 해결하기 위해 syncrhonized 를 사용할 경우 해당 메서드에는 @Transactional 을 붙여서는 안된다고 설명해 주셨습니다.

실제로 이를 붙일 경우, 동시에 decrease 메서드가 호출되고 해당 로직 내부로 들어가는 것이 가능함을 확인하였습니다.

 

그런데 여기서 제가 의문이 들었던 것이 있습니다.

@Transacitonal 을 사용할 경우 Spring AOP 에 의해 매 번 다른 proxy 인스턴스를 통해 target object 로의 호출을 하게 됩니다.

proxy 객체에 대한 lock 은 서로 다른 프록시들 사이에 공유되지 않는다고 하더라도, 내부적으로 호출되는 target 객체에 대한 decrease 메서드는 결국 동일한 객체에 대한 호출을 하기 때문에, 공유되는 lock 에 대한 경쟁이 일어나는 것이 아닌가 생각이 들었습니다.

최종적으로는 target 객체에 대한 synchronized 메서드를 호출하는 것이라면, 단 하나의 스레드만 임계 영역에 들어갈 수 있어야 할 것 같은데, 그렇지 않음을 확인하였습니다.

 

 

왜 이런 일이 일어나는 것인지 이해가 잘 되지 않습니다 ㅠㅠ

이와 관련해서 어떤 키워드로 공부해보면 좋을지 추천 가능할까요..?

답변 2

·

답변을 작성해보세요.

1

스빈스빈별님 안녕하세요.
syncrhonized 메소드에 Transactional 을 붙이게 된다면 아래와 같은 순서로 동작하게 될 것입니다.

class DemoServiceProxy {

     DemoService demoService;

     public void demo() {
          try {
               transaction.start()
               demoService.decrease()
          } catch(Exception e){
               transaction.rollback()
          } finally {
               transaction.commit()
          }
     }
}

class DemoService {

     synchronized public void decrease() {
           // 수량 감소
     }

}

 

이렇게 동작할때 demoService 의 decrease 메소드가 모두 동작되고 트랜잭션이 커밋할때까지 잠깐의 텀이 발생하게 됩니다. 이 텀 사이에 다른 스레드가 demoService 의 decrease 에 접근할 수 있게되고 그로인해 문제가 발생하게 됩니다.

그림으로 그려보면서 차근차근 따라가보시면 도움이 되실 것 같습니다.

감사합니다.

0

ocean blue님의 프로필

ocean blue

2023.11.12

안녕하세요. 제가 이해한게 맞는지 궁금해서 여쭤봅니다.

  1. @Transactional에서 고립 레벨 디폴트가 read_committed 이고, synchronized는 quantity를 동기화할 뿐, 트랜잭션의 시작과 끝을 동기회하지는 않음.

  2. 그래서 여러 스레드에서 트랜잭션이 동시에 시작되고, 모든 트랜잭션들이 자신의 트랜잭션이 시작되기 전에 커밋된 quantity == 100개의 상태일 때 접근하게 됨. (

    read_committed이면 다른트랜잭션이 커밋한 내용이 보이는데,아직 다들 커밋을 안한 상태라서 현재 모두들 공유자원이 100개로 보이는 상태.)

  3. 이 순간에 quantity가 동기화되면서 하나의 스레드씩만 접근을 해서 quantity를 줄이고, 그 quantity에 대한 락이 풀림. 그리고 먼저 실행된 트랜잭션이 커밋되려고 하는데, 다른 트랜잭션이 그때 락이 풀려있는 quantity에 접근할 수 있음.

위 내용대로 이해했는데 맞을까요?