상세 컨텐츠

본문 제목

[자바 CS지식] 스레드 안정성이란 무엇일까?

JAVA

by 소란한소란 2024. 2. 10. 21:51

본문

728x90

자바에서 "스레드 안전성"은 다중 스레드 환경에서 프로그램이 정확하게 동작하는 것을 보장하는 속성을 나타냅니다. 다중 스레드 환경에서 여러 스레드가 동시에 코드를 실행할 때, 데이터 무결성과 예측 가능한 동작을 유지하는 것이 중요합니다.

 

 

왜 스레드 안전성이 중요한가요?

자바에서는 멀티스레드 프로그래밍이 흔하며, 여러 스레드가 동시에 실행될 수 있습니다. 이때 하나의 자원을 여러 스레드가 동시에 접근하면 예상치 못한 결과가 발생할 수 있습니다. 스레드 간의 경쟁 조건, 데드락, 그리고 다른 동기화 문제들이 발생할 수 있기 때문에 스레드 안전성은 중요한 고려사항이 됩니다.

 

어떻게 스레드 안전성을 보장할 수 있나요?

Synchronization (동기화): 여러 스레드가 동시에 공유된 자원에 접근하는 것을 제어하기 위해 synchronized 키워드나 Lock 인터페이스를 사용합니다. 이를 통해 한 번에 하나의 스레드만이 임계 영역에 접근할 수 있도록 합니다.

public class SynchronizedExample {
    private int count = 0;

    // synchronized 키워드를 사용하여 메서드를 스레드 안전하게 만듭니다.
    public synchronized void increment() {
        count++;
        System.out.println("현재 카운트: " + count + " (스레드: " + Thread.currentThread().getName() + ")");
    }

    public static void main(String[] args) {
        SynchronizedExample example = new SynchronizedExample();

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                example.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                example.increment();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("최종 카운트: " + example.count);
    }
}

 

Immutable Objects (불변 객체): 객체가 한 번 생성되면 그 상태를 변경할 수 없는 불변 객체를 사용하면 스레드 안전성을 보장할 수 있습니다. 불변 객체는 여러 스레드가 동시에 접근해도 안전합니다.

public class ImmutableObjectExample {
    private final int value;

    // 생성자를 통해 값을 초기화하고, 이후에는 변경이 불가능한 불변 객체 생성
    public ImmutableObjectExample(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public static void main(String[] args) {
        ImmutableObjectExample immutableObject = new ImmutableObjectExample(42);

        // 여러 스레드에서 안전하게 접근 가능
        System.out.println("불변 객체의 값: " + immutableObject.getValue());
    }
}

 

Thread-Safe 자료 구조 사용: 자바에서는 java.util.concurrent 패키지에 스레드 안전한 자료 구조들이 제공됩니다. 예를 들어, ConcurrentHashMap과 같은 자료 구조를 사용하면 스레드 안전성을 갖춘 코드를 구현할 수 있습니다.

 

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ThreadSafeDataStructureExample {
    private static Map<String, String> threadSafeMap = new ConcurrentHashMap<>();

    public static void main(String[] args) {
        // 여러 스레드에서 안전하게 사용 가능한 ConcurrentHashMap
        threadSafeMap.put("key1", "value1");
        threadSafeMap.put("key2", "value2");

        // 다수의 스레드에서 안전하게 접근 가능
        System.out.println("스레드 안전한 Map: " + threadSafeMap);
    }
}

 

Atomic 변수 사용: java.util.concurrent.atomic 패키지에 있는 원자 변수(Atomic variables)를 사용하면 여러 스레드 간의 안전한 원자적 연산을 수행할 수 있습니다.

 

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicVariableExample {
    private static AtomicInteger atomicCounter = new AtomicInteger(0);

    public static void main(String[] args) {
        // 원자 변수를 사용한 안전한 증가 연산
        atomicCounter.incrementAndGet();

        // 다수의 스레드에서 안전하게 접근 가능
        System.out.println("스레드 안전한 원자 변수 값: " + atomicCounter.get());
    }
}

 

 

Thread-Local 변수: 스레드 간에 공유되지 않는 지역 변수를 사용하면 스레드 간의 간섭을 방지할 수 있습니다.

 

public class ThreadLocalExample {
    private static ThreadLocal<Integer> threadLocalValue = ThreadLocal.withInitial(() -> 0);

    public static void main(String[] args) {
        // 스레드 로컬 변수를 사용하여 각 스레드에 고유한 값 할당
        Thread thread1 = new Thread(() -> {
            threadLocalValue.set(42);
            System.out.println("스레드 1의 값: " + threadLocalValue.get());
        });

        Thread thread2 = new Thread(() -> {
            threadLocalValue.set(99);
            System.out.println("스레드 2의 값: " + threadLocalValue.get());
        });

        thread1.start();
        thread2.start();
    }
}

 

스레드 안전성은 멀티스레드 환경에서 안전하게 프로그램을 실행하기 위한 중요한 개념입니다. 적절한 동기화 기술과 안전한 자료 구조를 사용하여 다중 스레드에서의 데이터 접근을 조절하면 안정성을 유지할 수 있습니다. 프로그래머는 프로젝트의 특성에 맞게 적절한 스레드 안전성 기법을 선택하여 구현하는 것이 중요합니다.

 

 

728x90

관련글 더보기