CS 공부, 기타
스레드 세이프(thread safe)
Disciple428
2025. 3. 13. 00:30
- 스레드 세이프(thread safe)
멀티스레딩 환경에서 여러 스레드가 동시에 같은 코드 영역에 접근하거나 데이터를 공유할 때, 올바른 실행 결과를 보장하는 코드의 속성을 의미한다.
즉, 코드가 여러 스레드로부터 동시에 호출되더라도 각 스레드의 실행 경로가 서로를 방해하지 않도록 안전하게 설계되어 있다는 것이다.
이는 데이터 무결성과 일관성을 유지하는 데 필수적인 조건이다.
- 스레드 세이프를 보장하기 위한 전략
1. 상호 배제 (Mutual Exclusion)
한 시점에 하나의 스레드만이 특정한 코드 영역에 접근할 수 있도록 보장하는 방법으로, 일반적으로 많이 사용한다.
- 방법: synchronized 블록(자바), Mutex (Go, C++), 또는 다른 잠금 메커니즘을 사용하여 공유 데이터에 대한 접근을 제어
2. 불변성 (Immutability)
데이터가 생성 후 변경되지 않도록 하여 공유 데이터에 대한 동시 접근 문제를 해결
- 방법: 객체를 불변으로 만들어, 생성 시점에만 데이터를 할당하고 이후엔 변경할 수 없게 한다.
- 예시: 자바의 String 클래스, Go의 상수 사용
3. 스레드 로컬 저장소 (Thread-Local Storage)
각 스레드가 데이터의 자신만의 복사본을 가지고 있도록 하여 공유 데이터 문제를 회피
- 방법: ThreadLocal 클래스(자바) 사용, 각 스레드에서 고유한 인스턴스를 생성하고 사용한다.
- 예시: 자바에서 ThreadLocal 변수를 사용하여 각 스레드에 고유한 데이터 인스턴스를 제공
4. 원자적 연산 (Atomic Operations)
데이터에 대한 연산을 분할 불가능한 단일 단위로 만들어, 동시성 문제 없이 실행될 수 있도록 한다.
- 방법: AtomicInteger 같은 원자적 클래스 사용 또는 compareAndSwap 같은 원자적 하드웨어 지원 연산 활용
- 예시: 자바의 java.util.concurrent.atomic 패키지 내 클래스들, Go의 sync/atomic 패키지
5. 고립 (Isolation)
작업을 독립적으로 만들어 서로 영향을 주지 않도록 한다.
- 방법: 데이터베이스 트랜잭션에서 사용되는 고립 수준(isolation level) 설정 같이, 연산 간 영향을 줄이는 기술 사용
- 예시: 데이터베이스의 트랜잭션 관리, 메시지 큐를 통한 작업 분리
6. 락-프리 프로그래밍 (Lock-Free Programming)
락을 사용하지 않고 동시성 문제를 해결하여 데드락(deadlock)이나 락 경쟁(lock contention)으로 인한 성능 저하를 방지
- 방법: 원자적 연산을 활용하여 공유 데이터 구조를 업데이트하거나, 데이터 구조 자체를 락-프리(lock-free) 또는 웨이트-프리(wait-free)로 설계한다.
- 예시: 락-프리 큐, 카운터 등