Java

멀티 스레드 환경, 동시성 이슈, 해결방법 | 스레드 안전성 (Thread-safe)

Karla Ko 2023. 9. 14. 17:05
728x90

동시성 이슈

  • 멀티스레드 방식은 한 코어에서 여러 스레드를 이용해서 번갈아 작업을 처리하는 방식
  • 공유하는 영역이 많아 프로세스방식보다 context switcing 오버헤드가 작아, 메모리 리소스가 상대적으로 적다는 장점
  • 멀티스레드 프로세스의 경우 여러 스레드가 같은 프로세스 내의 자원을 공유해서 작업하기 때문에 서로의 작업에 영향을 줌
  • 여러 스레드가 동시에 하나의 자원을 공유하고 있기 때문에 같은 자원을 두고 경쟁상태(raceCondition) 같은 문제가 발생

2023.05.11 - [CS/OS] - [Process & Thread] 스레드, 멀티 스레드

 

[Process & Thread] 스레드, 멀티 스레드

1. 스레드 1) 스레드 하나의 프로세스 내에서 실행되는 동작의 단위 각 스레드는 프로세스의 스택 메모리를 제외한 나머지영역인 코드, 데이터, 힙 영역을 공유 프로세스 내에서 독립적인 기능을

karla.tistory.com

 

스레드 안전성 (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 ' 패키지에서 스레드 세이프한 컬렌션 클래스들을 제공
  • 스레드 간의 안전한 데이터 공유 가능
  • 대표적으로 HashtableConcurrentHashMapAtomicIntegerBlockingQueue
  • 자바는 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