728x90
동시성 이슈
- 멀티스레드 방식은 한 코어에서 여러 스레드를 이용해서 번갈아 작업을 처리하는 방식
- 공유하는 영역이 많아 프로세스방식보다 context switcing 오버헤드가 작아, 메모리 리소스가 상대적으로 적다는 장점
- 멀티스레드 프로세스의 경우 여러 스레드가 같은 프로세스 내의 자원을 공유해서 작업하기 때문에 서로의 작업에 영향을 줌
- 여러 스레드가 동시에 하나의 자원을 공유하고 있기 때문에 같은 자원을 두고 경쟁상태(raceCondition) 같은 문제가 발생
2023.05.11 - [CS/OS] - [Process & Thread] 스레드, 멀티 스레드
스레드 안전성 (Thread-safe)
- 여러 스레드가 동시에 접근하더라도 안전하게 동작하는 코드를 의미
- 다중 스레드 환경에서 발생할 수 있는 경쟁 조건, 데이터 불일치, 교착 상태 등과 같은 문제를 방지하고, 올바른 결과를 보장
- @ThreadSafe 어노테이션을 이용해 해당 Class가 Thread-Safe 함을 표시하기도 함
Thread - safe 종류
1. 동기화 메서드 synchronized
- 메서드의 접근을 동기화하는 방법으로, synchronized 키워드를 메서드 선언에 추가하여 사용
- 동기화를 사용하여 여러 스레드가 동시에 접근하는 코드 영역을 잠금하여 한 스레드만 실행할 수 있도록 함 (LOCK)
@ThreadSafe
public class Sequence {
@GuardedBy("this") private int nextValue;
public synchronized int getNext() {
return nextValue++;
}
}
public class PrivateLock {
private final Object myLock = new Object();
@GuardedBy("myLock") Widget widget;
void someMethod() {
synchronized (myLock) {
// Access or modify the state of widget
}
}
}
2. concurrent 패키지 하위 자료구조
- 자바에서는 ' java.util.concurrent ' 패키지에서 스레드 세이프한 컬렌션 클래스들을 제공
- 스레드 간의 안전한 데이터 공유 가능
- 대표적으로 Hashtable, ConcurrentHashMap, AtomicInteger, BlockingQueue
- 자바는 Hashtable 의 성능을 조금 더 증진시키기 위해 1.5 버전에서 ConcurrentHashMap을 도입
3. 원자적 연산
- 여러 Thread에서 안전하게 수행될 수 있는 원자적인 연산을 사용하여 여러 스레드에서 동시에 접근하더라도 올바른 결과를 보정
- 자바에서는 ' java.util.concurrent.atomic ' 패키지에서 ' AtomicInteger ' , ' AtomicBoolean ' , ' AtomicReference ' 등의 클래스를 제공
private AtomicInteger counter = new AtomicInteger();
public void incrementCounter(){
counter.incrementAndGet(); // 스레드 세이프한 연산
}
4. 불변 객체
- 변경할 수 없는 불변 객체를 사용하여 스레드 세이프한 코드를 구현
- 불변 객체는 한 번 생성되면 내부 상태가 변경되지 않기 때문에 동시에 여러 스레드가 접근해도 안전
- 적절한 final 키워드도 별다른 동기화작업이 없이도 동시성환경에서 자유롭게 사용할 수 있음
- 초기화된 이후에 변경될 수 없기 때문에 여러스레드가 동시에 접근해도 동일한 값을 보장받을 수 있기 때문
public final class ImmutableObject{
private final int value;
public ImmutableObject(int value){
this.value = value;
}
public int getValue(){
return value;
}
}
5. 스레드 로컬 변수
- 각 스레드마다 독립적인 변수를 사용하여 스레드간에 데이터를 공유하지 않고 유지할 수 있음
- 자바에서는 ThreadLocal 클래스를 사용하여 스레드 로컬 변수를 구현할 수 있음
private static TreadLocal<Integer> threadLocal = new ThreadLocal<>();
public void setValue(int value){
threadLocal.set(value); // 스레드별로 독립적인 값 설정
}
public int getValue()
728x90