-
Synchronized, Heavy-weight Lock 동작 원리, ReentrantLock과의 성능 비교
LogQueue를 구현하면서, 동기화 수단이 필요했는데 이때 synchornized를 사용하는 방법과 ReentrantLock을 사용하는 방법 중 어떤 것을 써야 할지 궁금해졌다. 둘의 차이는, 기본적으로 ReentrantLock을 쓰면 락을 명시적으로 제어 가능하면서, Condition의 대기 공간을 여러 개 만들 수 있다는 장점이 있었는데 이 외에는 성능 차이가 얼마나 나는지 궁금해졌다. 둘 다 내부적으로 spin 등을 이용하여 최적화가 잘 되어있는데, light-weight한 경우와 heavy-weight 한 경우에 대해 모두 다 성능 차이가 얼마나 있을지 비교해 보기로 했다.LogQueue에 동기화 별 성능 차이 비교LogBat 프로젝트에서 사용했던 LogQueue에 대해 동기화 수단을 Reent..
2024.10.03 16:37 -
제네릭 배열은 왜 안 될까?, TypeReference는 어떻게 런타임에 제네릭 타입 정보를 보존할까?
배열과 제네릭의 타입 소거일반적으로 제네릭은 컴파일 시점에만 컴파일을 보장하고, 런타임에는 타입을 Object로 통일 해버린다. (예외 경우로 extend로 bound를 제한하는 경우에는 아닐 수도 있다.) 이를 타입 소거라고 하는데, 이것 때문에 런타임에는 제네릭의 원래 타입을 알 수 없다.이러한 타입 소거 때문에, Java에서는 제네릭 배열 생성이 금지된다.List[] lists = new ArrayList[100]; // [] lists = new ArrayList[100]; //이렇게 하면 오류는 안 생김이러한 이유는, 배열이 런타임에 타입을 검사를 한다는게 주요한데,만약 컴파일 단계에서 잡히지 않고, List[] lists에, new ArrayList()를 넣으려고 하더라도, 제네릭은 Objec..
2024.09.26 16:38 -
Condition이 동작하는 원리 (ReentrantLock + AbstractQueuedSynchronizer)
Condition의 존재 이유는, Mutex는 상호배제를 위한 도구이고, 동기화를 위한 수단이 아니다. 따라서 특정 조건이 충족될 때까지 대기하거나 작업 간의 순서를 조정하는 기능을 제공하지 못한다. Condition 변수는 왜 필요한 걸까?특정 스레드가 어떤 상태 또는 행위를 수행하기를 기다리는 방법이다. 예를 들면, 문자가 buffer에 추가되길 기다릴 때 사용될 수 있다. 즉, 특정 상태가 true가 되기를 기다리는데 Condition Variable이 이용된다. 출처:https://web.stanford.edu/~ouster/cgi-bin/cs140-spring14/lecture.php?topic=locks Locks and Condition VariablesLocks and Condition V..
2024.09.22 21:32 -
ReentrantLock이 동작하는 원리 (AbstractQueuedSynchronizer)
이번에 OpenJDK에 이슈를 작성하면서 ReentrantLock에 대해서 깊게 공부할 기회가 생겼다. OpenJDK 컨트리뷰터와 이야기하면서 얻은 지식이 파편화되어 있어 한 번 글로 써보면서 큰 흐름을 정리하고 싶어 글을 작성했다.자바에서는 기본적으로 모니터락을 사용하는 syncrhonized가 있다. synchronzied 키워드 하나만으로도 임계영역의 스레드 접근을 제어할 수 있지만, 내부적으로 blocking 되었을 때 interrupt 등으로 취소할 수도 없고 타임아웃 기능도 없다. synchroinized 또한 재진입 가능, wait도 모두 가능하지만, wait 할 수 있는 대기 공간이 하나로 제한돼 있는 점들이 있다는 단점이 있다. 이를 해결하기 위해 코드 상으로 유연하게 락을 걸 수 있는..
2024.09.17 17:38 -
우아한 테크캠프 7기 합격 + 2주차 후기
우아한 테크캠프 7기(백엔드)에 합격했던 과정과 2주 동안 참여한 후기를 작성해보려고 합니다. 우아한 테크 캠프에 참여하기 까지코딩 테스트알고리즘 3문제 + CS 객관식 5문제를 프로그래머스에서 진행했습니다.코딩 테스트 언어가 Java로 제한되어 있어 알고리즘 난이도가 어렵지 않을 거라고 생각했었고, 실제로도 그랬던 기억이 납니다. 1번 2번 난이도는 무난해서 푸는데는 25분 안으로 끝냈던 것 같고, 3번이 어려운 건 아닌데 처음 보는 아이디어가 필요했던 이분 탐색 문제라 구현을 헤맸습니다. 이후 반례를 찾으려 테스트 케이스 돌려보다 2번에서 특이한 반례를 찾아 그 부분을 고쳐서 제출했습니다. CS 객관식 문제는 크게 어렵지 않아서 쉽게 맞췄던 거 같습니다. 하지만 CS 객관식 문제가 추론을 요하는 문제..
2024.07.07 23:00 -
@Async 메서드를 @Transactional 내에서 테스트하는 방법
@Async로 실행하는 메서드에 대해 @Transactional 테스트를 수행하게 되면 문제가 발생합니다. (주석은 무시하셔도 좋습니다)위 메서드에 대해 테스트를 수행하기 위해 위와 같이 저장 후 테스트를 수행하여 검증하는 로직이 있는데, 값이 정상적으로 update되어 저장됐는지를 확인해야하지만, 분명히 동기적으로 작동시켰을 때는 정상적으로 동작했던 코드임에도 불구하고 @Async 옵션을 통해 수행하면 오류가 발생했습니다. 또한, 해당 메서드에서는 given에서 분명히 저장했던 Submit을 찾을 수 없다는 예외가 발생합니다. 이는 테스트 메서드에 달려있는 @Transactional로 인해, 현재 "Submit" 인스턴스를 저장한 트랜잭션이 커밋되지 않은 상태에서 다른 비동기 스레드가 해당 사항을 조..
2024.06.07 17:25 -
[Spring Batch] 직접 AbstractPagingItemReader를 구현하여 도메인에 특화된 PagingCollectionsItemReader 만들어보기
모두의 랜덤 디펜스에서는 '백준'의 문제 데이터를 이용하여 코딩테스트 문제를 제공합니다. '백준' 문제의 메타데이터는 시간이 갈수록 쌓일 것이고, 이를 자체 DB에 주기적으로 업데이트 하는 과정이 필요했습니다. 데이터베이스에 저장된 백준 문제들은 정기적으로 업데이트되어야 합니다. 이 목적을 달성하기 위해 solved.ac API를 활용하며, 이 API의 URL 구조는 다음과 같습니다.https://solved.ac/api/v3/search/problem?query={query}&page={page}특정 문제의 데이터를 조회할 때, {query}에 'id:1000'과 같은 문제 ID를 입력함으로써 접근할 수 있습니다. 문제 메타데이터 업데이트 과정 1. DB에서 문제 정보를 읽어온다.2. 문제 메타 데이터..
2024.05.12 21:48 -
MockMvcBuilders.standaloneSetup()에서 LocalDateTime 직렬화 문제 해결 방법
Meta: MockMvcBuilders, standaloneSetup, LocalDateTime, 직렬화, SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, Spring Boot, MockMvc, Jackson, ObjectMapper, 테스트 코드MockMvcBuilders.standaloneSetup()에서 LocalDateTime 직렬화 문제 해결 방법RestDocs를 사용하여 MockMvcBuilders.standaloneSetup()으로 구성된 테스트에서 LocalDateTime 직렬화 문제를 해결하는 방법을 소개합니다.The documented type of the field '{field Name}' is String but the actual type i..
2024.05.01 13:39