ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Kotlin] @Synchronized 어노테이션 동작 방식
    📖 개발 공부/kotlin 2023. 8. 3. 00:50
    한줄요약: @Synchronized 어노테이션은 AOP와 관련된 게 아니라 synchronized JVM 메서드임을 알려주는 역할을 한다!

     

    동시성 이슈 강의 스터디를 할 때 나는 코틀린으로 변환해서 코드를 작성하였다.

     

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

    인프런 재고시스템으로 알아보는 동시성이슈 해결방법 강의를 보면서 정리한 내용입니다. 재고시스템으로 알아보는 동시성이슈 해결방법 - 인프런 | 강의 동시성 이슈란 무엇인지 알아보고 처

    ayoung0073.tistory.com

    이때 synchronized 키워드를 쓸 수 없어 같은 동작을 하는 @Synchronized 어노테이션을 붙였다.

     

    그리고 스터디 발표가 당청되어 내가 작성한 코드를 보며 발표를 하던 중..!

     

    스터디를 같이 하는 팀원이 물었다.

    @Service
    class StockService(
        private val stockRepository: StockRepository
    ) {
        @Synchronized
        fun decrease(id: Long, quantity: Long) {
            val stock = stockRepository.findById(id).orElseThrow()
            stock.decrease(quantity)
            stockRepository.saveAndFlush(stock)
        }
    }
    

     

    "위의 코드를"

     

    @Service
    class StockService(
        private val stockRepository: StockRepository
    ) {
        fun decrease1(id: Long, quantity: Long) {
            decrease(id, quantity)
        }
        
        @Synchronized
        fun decrease(id: Long, quantity: Long) {
            val stock = stockRepository.findById(id).orElseThrow()
            stock.decrease(quantity)
            stockRepository.saveAndFlush(stock)
        }
    }
    

    "이 코드로 바꾸면 잘 동작할까요? AOP 방식으로 동작하는 게 맞나요??"

     

     

    나는 AOP로 어노테이션을 만들어본 경험뿐이어서 잘 몰랐다.

    그래서 우린 동작하지 않을거야..! 같은 클래스 내 AOP 어노테이션이 달린 메서드를 호출하면 동작하지 않으니까 락이 걸리지 않을거야..!

    라 예상했지만 테스트가 성공해버렸다;;

     

    나는 그저 Java의 synchronized 키워드와 같은 아이인줄 알고 붙였더니만,, 혼란스러워졌다!

     

    그래서 @Synchronized 어노테이션을 알아보는 시간을 가졌다.

     

    우선 @Synchronized 어노테이션 관련해서 간략한 설명!

     

    @Synchronized 어노테이션을 사용하면 내부적으로 해당 메소드 또는 코드 블록은 mutex 라는 락을 사용하여 동기화가 이루어진다. 한 번에 하나의 스레드만 락을 소유할 수 있으며, 다른 스레드가 락을 소유하는 동안에는 해당 코드 블록 또는 메소드에 접근할 수 없다. 이렇게 함으로써 여러 스레드가 동시에 같은 데이터에 접근하여 발생할 수 있는 문제를 방지할 수 있다.

     

    다음은 Synchronized 어노테이션에 대한 공식 문서 내용이다.

    @Target(FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER)
    @Retention(AnnotationRetention.SOURCE)
    @MustBeDocumented
    public actual annotation class Synchronized
    
    Marks the JVM method generated from the annotated function as synchronized, meaning that the method will be protected from concurrent execution by multiple threads by the monitor of the instance (or, for static methods, the class) on which the method is defined.

    Note that for an extension function, the monitor of the facade class, where it gets compiled to a static method, is used. Therefore, this annotation is recommended to be applied only to member functions and properties. In other cases, use synchronized)) function and explicitly specify the lock to be used.

     

     

    Kotlin 컴파일러는 @Synchronized 어노테이션이 적용된 메소드 또는 코드 블록을 컴파일할 때, 해당 코드를 동기화된 블록으로 변환한다. 이 변환 과정에서 컴파일러는 JVM 레벨에서 mutex 락을 사용하는 코드로 변경한다. 따라서, 이 변경된 코드는 실행 시간에 mutex 락이 필요한지 여부를 JVM이 결정하게 된다. (= 동기화 메커니즘 구현은 JVM에 의해 수행된다.)

    이러한 작업은 컴파일 시간에 수행되므로, 실제로는 컴파일러가 mutex 락을 설정하는 것이 아니라 해당 코드가 mutex 락을 사용하도록 지시하는 코드로 변환하는 것 이다. 


    요약하자면,

    AOP 관련 어노테이션이 아니다.!!!

    이 어노테이션은 Kotlin 컴파일러에게 이 메소드 또는 코드 블록이 동기화되어야 함을 나타내는 플래그를 설정하는 역할을 하고, 실제로 락을 설정하고 관리하는 것은 JVM이다.

    Kotlin 컴파일러는 이 어노테이션을 발견하면 JVM의 synchronized 플래그를 포함하는 바이트코드로 변환한다.

    Java의 synchronized 키워드와 같은 역할을 한다!!


    한줄요약

    @Synchronized 어노테이션은 AOP와 관련된 게 아니라 synchronized jvm 메서드임을 알려주는 역할을 한다!

     

    728x90
    반응형

    댓글

Designed by Tistory.