投稿
Q&A
질문있습니다.
안녕하세요, 조성우님!큰 그림은 맞게 이해하셨어요. 다만 한 가지 디테일을 추가로 알아 주셔야 합니다. 기본 분류는 말씀하신 그대로입니다.읽기만 수행 (가시성만 보장하면 충분): volatile읽기 + 쓰기 (원자성도 필요): synchronized 또는 Atomic 다만 알아두시면 좋은 점은, synchronized는 원자성뿐 아니라 가시성 문제도 함께 해결한다는 점이에요. 자바 메모리 모델(JMM)이 락 획득/해제 시점에 다음을 보장하기 때문입니다. 락 획득 (synchronized 진입): CPU 캐시를 무효화하고 메인 메모리에서 최신 값을 다시 읽어옴락 해제 (synchronized 종료): 변경된 값을 메인 메모리로 flush 즉 synchronized 블록에 진입하거나 빠져나갈 때마다 메모리 배리어가 동작해서 가시성이 자연스럽게 보장됩니다. Atomic 클래스들도 내부적으로 volatile 변수와 CAS 연산을 사용하기 때문에 마찬가지로 가시성을 함께 보장하고요. 정리하면 이렇습니다.가시성만 필요할 때 → volatile (가장 가볍고 성능 좋음)원자성도 필요할 때 → synchronized 또는 Atomic (둘 다 가시성도 자동 해결)
- いいね数
- 1
- コメント数
- 2
- 閲覧数
- 61
Q&A
팬텀리드 해결 예시 질문
안녕하세요, Cola님!정확히 짚어주셨습니다. 좋은 지적 감사합니다. 말씀하신 대로 SELECT ... FOR UPDATE WHERE id = 5에서 id가 PK이고 해당 row가 존재한다면, InnoDB는 갭락 없이 레코드 락만 걸립니다. MySQL 공식 매뉴얼(17.7.3 Locks Set by Different SQL Statements in InnoDB)에도 명시되어 있는 동작이에요. "For a unique index with a unique search condition, InnoDB locks only the index record found, not the gap before it." 실제로 performance_schema.data_locks 테이블에서 확인하시면 X, REC_NOT_GAP(record lock only)으로 찍히는 케이스에 해당합니다. 전체 락 동작을 정리하면 다음과 같습니다. InnoDB 락 동작 정리 (REPEATABLE READ 기준)Unique Index + 정확한 값 + row 존재 => Record lock만 (갭락 X)Unique Index + 정확한 값 + row 없음 => Gap lockNon-Unique Index => Next-key lock (Record + Gap)범위 조건 (BETWEEN, >, Next-key lock (Record + Gap) InnoDB가 팬텀 리드를 막기 위해 기본적으로 next-key lock을 사용하는 큰 그림은 그대로 맞지만, 질문하신 케이스(Unique Index 단일 매치)는 유일성 보장 자체가 팬텀을 원천 차단하기 때문에 InnoDB가 최적화로 레코드 락만 거는 예외 케이스에 해당해요. 자료의 예시(WHERE id = 5)는 next-key lock이 실제로 걸리는 케이스(범위 조건 또는 Non-Unique Index)로 교체하고, 위의 락 동작 정리 표를 보강 자료로 추가해두겠습니다. 디테일까지 정확하게 짚어주신 덕분에 자료가 한 단계 더 정밀해질 것 같아요. 정말 감사합니다! 참고 링크MySQL 공식 매뉴얼 17.7.3 — 표의 모든 케이스가 명시되어 있습니다https://dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html당근 테크 블로그 — MySQL Gap Lock 다시보기 — Real MySQL 8.0 공저자(백은빈)가 작성한 한국어 설명, 그림과 예시가 풍부합니다https://medium.com/daangn/mysql-gap-lock-다시보기-7f47ea3f68bc
- いいね数
- 1
- コメント数
- 1
- 閲覧数
- 53
Q&A
MySql
안녕하세요, Cola님!좋은 질문이에요. 정확히는 MySQL(InnoDB)이 사용하는 인덱스 구조는 B+Tree가 맞습니다. 다만 강의에서 B-Tree를 다룬 건 면접 빈출 패턴을 고려한 선택이에요. 면접에서는 보통 "인덱스 자료구조를 설명해주세요" 또는 "B-Tree를 설명해주세요"라는 식의 질문이 훨씬 자주 나오고, B+Tree는 그 위에 얹어지는 변형 구조라 B-Tree를 먼저 정확히 이해하시면 B+Tree는 자연스럽게 따라옵니다. B+Tree는 B-Tree에서 다음 두 가지가 추가/변경된 형태로 보시면 됩니다.데이터는 leaf node에만 저장 (internal node는 key만 가짐)Leaf node끼리 연결 리스트로 이어져 범위 검색에 유리 균형 트리 특성, 분할/병합 동작, 탐색 시간 복잡도 같은 핵심 메커니즘은 B-Tree와 동일합니다. 그래서 면접에서 "MySQL의 인덱스는 어떻게 동작하나요?" 같은 질문이 들어오면, B-Tree 설명을 베이스로 깔고 → "InnoDB는 이 위에서 B+Tree로 변형해 leaf node에만 데이터를 저장하고, leaf끼리 연결 리스트로 묶어 범위 검색을 빠르게 만들었다" 정도로 풀면 깊이 있는 답변이 됩니다. 즉 B-Tree는 베이스, B+Tree는 그 위의 특화 구조로 이해해주시면 강의에서 B-Tree를 다룬 의도가 자연스럽게 이어집니다.
- いいね数
- 1
- コメント数
- 2
- 閲覧数
- 55
Q&A
멀티스레드
안녕하세요, Cola님! 람다와 스트림이 멀티스레드 환경에 안전하다는 건 "순수 함수로 사용한다는 전제 아래" 안전하다는 의미예요.스트림 API는 각 연산이 stateless하고 부수효과를 일으키지 않는다는 것을 전제로 설계되어 있습니다. 이 전제만 지키면 parallelStream()으로 병렬 처리해도 race condition 없이 안전하게 동작합니다. Java 공식 문서에서도 스트림 연산은 stateless해야 한다고 명시되어 있고요. 말씀하신 대로 람다 내부에서 외부 변수를 수정하거나 공유 상태에 부수효과를 일으키면 당연히 안전하지 않습니다. 다만 이 경우는 스트림이 안전하지 않은 게 아니라, 함수형 프로그래밍의 설계 원칙을 사용자가 깬 것이라고 보시는 게 맞아요. 자료에서 "안전하다"고 한 건 의도된 사용 방식, 즉 순수 함수로 작성하는 경우를 전제한 표현입니다. 면접에서는 "스트림은 stateless한 순수 함수로 작성하는 것을 전제로 설계되어 있어서, 이 약속만 지키면 parallelStream()에서도 안전하게 동작합니다. 부수효과가 있는 람다를 쓰면 그건 함수형 원칙을 깬 것이지 스트림의 한계는 아닙니다" 정도로 답변하시면 됩니다.
- いいね数
- 1
- コメント数
- 2
- 閲覧数
- 58
Q&A
성능 오버헤드
안녕하세요, Cola님!사실 일반적인 시스템에서 instanceof로 인해 성능 상의 큰 문제가 되는 건 많지는 않습니다.정확히는 상속의 깊이가 깊어지고, 해당 상속으로 이어지는 클래스가 많을 경우 이들을 순회하면서 타입을 찾는데요! 이러한 수십 ~ 수백 개 이상의 클래스가 상속 구조로 연결된 형태가 많은 거대한 애플리케이션이라면 문제가 생길 여지가 있습니다. 물론 이보다는 다형성을 깨뜨리는 점이 더 메인 문제점이지만, 성능 오버헤드도 알아두면 좋겠어서 자료로 포함하게 되었습니다.
- いいね数
- 1
- コメント数
- 2
- 閲覧数
- 53
Q&A
volatile에 대해 질문 있습니다.
안녕하세요, Cola님!꽤 좋은 질문을 해주셨네요 ㅎㅎ 두 설명은 사실 모순되는 게 아니라 서로 다른 측면을 다루고 있습니다.우리 자료의 설명: 가시성 문제가 왜 발생하는지 => 코어별 캐시 구조가 근본 원인다른 자료의 설명: volatile이 어떻게 해결하는지 => happens-before와 메모리 배리어 우리 자료에서 설명하는 "코어별 캐시로 인한 가시성 문제"는 자바 메모리 모델 학습의 표준 출발점이고, 멀티 코어 환경에서 각 CPU 코어가 독립적인 캐시를 갖기 때문에 가시성 문제가 발생한다는 점은 정확한 설명입니다. Cola 님이 보신 다른 자료는 volatile이 이 문제를 어떻게 해결하느냐를 다루는 부분이에요. Java 5(JSR-133) 이후 volatile은 happens-before 관계 형성과 메모리 배리어 삽입으로 동작하며, 이 메모리 배리어가 실행될 때 결국 CPU 캐시 일관성을 강제 동기화하는 효과를 냅니다. 두 설명은 같은 현상의 원인과 해결 메커니즘을 각각 다루는 것이라, 충돌이 아닌 상호 보완 관계입니다.면접에서 만약 둘을 묶어서 답변하시고 싶다면, 아래 형태를 고려해보시면 됩니다! "멀티 코어 환경에서 각 코어가 독립적인 캐시를 갖기 때문에 가시성 문제가 발생합니다. volatile은 happens-before 관계와 메모리 배리어를 통해 이 캐시 간 동기화를 강제하여, 다른 스레드가 최신 값을 읽을 수 있게 보장합니다."
- いいね数
- 2
- コメント数
- 2
- 閲覧数
- 85
Q&A
GC 알고리즘
안녕하세요, Cola님!Mark and Sweep을 핵심 키워드로 가져가시는 건 충분히 괜찮습니다. Mark는 모든 GC 알고리즘의 공통 출발점이라, 어느 컬렉터를 쓰더라도 "GC Root에서 시작해 reachable 객체를 마킹한다"는 점은 동일하기 때문이에요. 다만 면접 답변을 더 풍성하게 가져가시려면, Mark and Sweep 외에 함께 알아두시면 좋은 알고리즘 두 가지가 있습니다.Mark and Compact: 마킹 후 살아남은 객체를 한쪽으로 모아 정리 → Mark and Sweep의 단편화 문제를 해결, Old Generation에서 사용Copying: 살아남은 객체를 다른 영역으로 복사 → Young Generation의 Eden ↔ Survivor 사이 이동에 사용 전체 구조로 정리하면 이렇습니다.[GC의 큰 틀] └ Mark and Sweep (마킹 → 정리) [영역별 정리 방식] ├ Young Generation : Copying └ Old Generation : Mark and Sweep / Mark and Compact 면접에서 "GC 동작 원리"가 메인 질문으로 나오면 Mark and Sweep을 출발점으로 답변하시고, 후속 질문이 들어올 때 위 두 알고리즘으로 확장하시면 됩니다!
- いいね数
- 1
- コメント数
- 2
- 閲覧数
- 60
Q&A
Mark and Sweep
안녕하세요, Cola님!자료의 "Mark and Sweep" 표현은 마킹을 통해 비활성 객체를 정리한다는 GC 동작의 큰 흐름을 통칭하는 의미로 사용한 것입니다. Mark는 모든 GC 알고리즘의 공통 1단계라, GC의 핵심 원리로 함께 언급되는 경우가 많습니다. 더 엄밀한 알고리즘 분류로는 영역별로 나뉩니다.Young Generation (Eden ↔ Survivor): Copying 방식 (말씀해 주신 내용)Old Generation: Mark and Sweep / Mark and Compact
- いいね数
- 1
- コメント数
- 1
- 閲覧数
- 59
Q&A
용어 질문
안녕하세요, Cola님!두 표현 모두 같은 개념을 가리키는 유효한 표현이고, 의미상 차이는 없습니다.Root Space: GC가 reachability 분석을 시작하는 출발점이 위치한 영역을 가리키는 표현GC Root / GC Roots: 같은 개념을 영문 표준 자료(Eclipse MAT, JVM 공식 문서, Baeldung 등)에서 자주 부르는 표현둘 다 스택의 로컬 변수, 정적 변수, JNI 참조, 활성 스레드처럼 "GC가 traverse를 시작하는 기점"을 의미하며, 어느 표현을 사용하셔도 무방합니다!
- いいね数
- 1
- コメント数
- 1
- 閲覧数
- 39
Q&A
호출횟수 질문입니다.
안녕하세요, Cola님! 자료의 2,000 / 15,000은 HotSpot JVM의 Tiered Compilation 기본값으로, -XX:Tier3CompileThreshold, -XX:Tier4CompileThreshold 옵션에 해당합니다. 이 값은 Tiered Compilation이 기본 활성화된 Java 8 이후 최신 OpenJDK HotSpot까지 동일하게 유지되고 있습니다. OpenJDK 소스 트리의 테스트 코드(CheckCompileThresholdScaling.java)에서도 같은 값으로 검증되고 있습니다. 그래서 OpenJDK HotSpot 기준으로는 버전 차이를 신경 쓰지 않으셔도 됩니다. 직접 확인하시려면 다음 명령어를 수행해 보시면 됩니다.java -XX:+PrintFlagsFinal -version | grep CompileThreshold 다른 JVM 벤더(OpenJ9, GraalVM 등)는 정책이 달라 수치가 다를 수 있지만, OpenJDK HotSpot 기준으로 약 2,000 / 약 15,000으로 외워두시면 충분합니다. 참고: https://devblogs.microsoft.com/java/how-tiered-compilation-works-in-openjdk/
- いいね数
- 1
- コメント数
- 2
- 閲覧数
- 55




