hyeonga_code

JVM_20_스레드간 통신을 위해 사용되는 기법 본문

JVM

JVM_20_스레드간 통신을 위해 사용되는 기법

hyeonga 2024. 5. 21. 06:59
반응형

 
 

1. 공유 메모리 기법

스레드들이 공유하는 메모리 영역을 사용하여 데이터를 공유합니다.
스레드는 공유 변수나 객체를 통해 서로의 상태를 체크하고 조작할 수 있습니다.


volatile
키워드를 사용한 변수

synchronized
블록을 통한 동기화

Amonic
클래스 등을 사용하여 데이터 일관성과 스레드 안전성을 보장합니다.

 
 
 
 

2. 메세지 전달 기법

스레드 간의 메세지를 명시적으로 보내고 받는 방식입니다.
스레드가 직접적으로 데이터를 공유하지 않고 메세지를 통해 필요한 정보를 교환합니다.


BlockingQueue
같은 스레드 안전한 큐를 사용하여 스레드 간에 메세지를 전달할 수 있습니다.
생산자 스레드는 큐에 데이터를 넣고 소비자 스레드는 데이터를 꺼내 처리합니다.

 
 
 


공유 메모리와 메세지 전달 비교

공유 메모리 기법

스레드들이 데이터를 빈번하게 읽고 쓰며 데이터 접근 시간이 중요한 경우 사용합니다.
메세지 전달 기법에 비해 일반적으로 오버헤드가 낮고 빠르게 데이터를 교환할 수 있습니다.
데이터를 공유하고 동기화 매커니즘을 통해 데이터의 일관성을 유지할 수 있어 효율적입니다.
공유 메모리 기법은 데이터를 중앙화하여 여러 스레드가 쉽게 접근할 수 있게 하여 구현이 비교적 단순하고 데이터 처리 성능이 높습니다.
그러나 동기화를 잘못하는 경우 데이터 경쟁 상황, 교착 상태, 기아 상태 등의 문제가 발생할 수 있습니다.
 

메세지 전달 기법

다른 메모리 공간에 있는 프로세스 간에 데이터를 교환해야 하는 경우 사용합니다.
시스템의 각 부분을 독립적으로 유지하고 싶은 경우 유리합니다.
메세지 기반 아키텍처라는 시스템 컴포넌트를 느슨하게 연결하여 시스템을 확장하거나 변경하기에 용이합니다.
명시적인 메세지 형태로 데이터를 교환함으로써 스레드 간의 독립성을 유지할 수 있습니다.
이는 스레드나 프로세스의 결합도를 낮추고 시스템의 각 부분을 독립적으로 개발하고 테스트할 수 있는 장점을 제공합니다. 메세지 전달 기법은 스레드 간의 상태 공유 없이도 동작할 수 있으므로 데이터 경쟁이나 교착 상태의 위험을 크게 줄일 수 있습니다.
 

공유 메세지와 메세지 전달의 결합

1) 실시간 시스템

실시간 데이터 처리가 필요한 시스템에서는 저지연으로 데이터를 처리해야 합니다.
공유 메모리 기법을 통해 빠른 데이터 접근과 처리가 가능하고 메세지 전달 기법을 통해 시스템 간의 교환을 명확하게 할 수 있습니다.
공유 메모리 기법은 빠른 응답 시간을 제공하며 메세지 전달 기법은 프로세스 간의 독립성을 유지하고 시스템의 확장성을 보장합니다.
 

2) 대규모 분산 시스템

클라우드 컴퓨팅, 대규모 클러스터링 환경에서는 여러 노드가 협업하여 대량의 데이터를 처리합니다.
메세지 전달 기법을 통해 데이터 교환과 함께 노드 내부에서는 공유 메모리를 사용하여 데이터를 효율적으로 관리할 수 있습니다.
메세지 전달 기법은 네트워크를 통한 효율적인 데이터 교환을 가능하게 합니다.
공유 메모리 기법은 개별 노드 내에서의 빠른 데이터 접근과 처리를 지원합니다.
 

3) 복잡한 멀티 스레딩 애플리케이션

고성능 컴퓨팅이나 게임 엔진과 같은 애플리케이션에서는 여러 스레드가 고도로 상호작용하며 데이터를 처리합니다.
내부 스레드 간에는 공유 메모리 기법을 사용하여 스레드 간에 빠른 데이터 공유를 가능하게 합니다.
모듈 간에는 메세지 전달 기법을 사용하여 모듈 간의 결합도를 낮추고 유연한 시스템 구조를 제공합니다.
 


 

3. 조건 변수와 락 기법

스레드가 특정 조건이 충족할 때까지 대기하게 하고, 조건이 충족되면 스레드를 깨워 작업을 계속하게 하는 방식입니다.


Object 클래스의 wait(), notify(), notifyAll() 메소드를 사용하거나 java.util.concurrent.locks 패키지의 ReentrantLock, Condition 인터페이스를 사용하여 더 세밀한 통제를 수행합니다.

 
 
 

4. 세마포어와 뮤텍스 기법

스레드가 리소스에 접근하기 전에 획득해야 하는 일종의 신호기인 세마포어와 세마포어의 한 형태인 뮤텍스가 한 번에 하나의 스레드만이 리소스를 사용할 수 있도록 제한합니다.
Semaphore 클래스를 사용하여 스레드 간에 리소스 접근을 조정할 수 있습니다.
뮤텍스는 synchronized 키워드나 ReentrantLock 을 사용하여 구현할 수 있습니다.
 
 

5. 이벤트와 신호 기법

스레드가 특정 이벤트를 기다리게 하고 이벤트가 발생하면 해당 스레드 또는 스레드 그룹을 깨워 처리를 계속하게 하는 방식입니다.
CountDownLatch, CycleBarrier, Phaser와 같은 동기화 도구를 사용하여 복잡한 스레드 간 조정 및 동기화를 수행합니다.


동기화의 필요성

데이터 일관성 보장

여러 스레드가 같은 메모리 데이터에 동시에 쓰기 작업을 수행하는 경우 데이터가 예상치 못하게 변경되거나 손상될 수 있습니다.
이러한 상황을 동기화가 관리하여 데이터의 정확성과 일관성을 유지합니다.
 

데드락 방지

데드락 : 두 개 이상의 스레드가 서로 다른 리소스를 기다리며 무한 대기하는 상태
 

경쟁 상태 해결

경쟁 상태 : 여러 스레드가 데이터에 동시에 접근하려고 할 때 발생하며 실행 순서에 따라 결과가 달라질 수 있습니다.
 
 

동기화의 문제점

성능 저하

동기화는 필요한 경우 스레드의 실행을 중단시키고 대기하게 만듭니다.
스레드의 실행 속도를 늦추고 애플리케이션의 전반적인 성능에 영향을 미칩니다.
 

복잡성 증가

동기화 로직을 구현하고 유지 관리하는 것은 복잡하며 코드의 이해와 디버깅을 어렵게 만듭니다.
 

데드락 위험

잘못된 동기화는 데드락을 초래할 수 있으며 이를 해결하기 위한 추가적인 설계와 관리가 필요합니다.
 
 

동기화의 문제점 해결 방법

락 사용

synchronized 키워드와 ReentrantLock 클래스를 사용하여 코드 블록 또는 메소드를 동기화 할 수 있습니다.
 

조건 변수 사용

스레드가 특정 조건이 충족될 때까지 대기하게 하고 조건이 충족되면 스레드를 깨우는 방식입니다.
Object 클래스의 wait(), notify(), notifyAll() 메소드 또는 Condition 인터페이스를 사용할 수 있습니다.
 

동시성 컬렉션 사용

java.util.concurrent 패키지는 스레드 안전한 컬렉션(ConcurrentHashMap, BlockingQueue) 를 제공하여 내부적으로 동기화를 관리합니다.
데이터 구조 자체에서 동기화를 처리하므로 개발자가 별도로 동기화를 관리할 필요가 줄어듭니다.
 

최소한의 공유 범위

공유되는 데이터의 범위를 최소화하고 가능하면 불변 객체를 사용하여 스레드 간에 데이터 공유를 줄입니다.
동기화 필요성을 줄이고 코드의 복잡성과 성능 저하 문제를 완화합니다.
 
 


커널 스레드 생성 

커널 스레드 : 운영 체제의 커널에 의해 직접 관리되는 스레드입니다.

시스템 자원을 직접 제어하고 커널 서비스를 수행할 수 있습니다.
커널 스레드는 운영 체제의 핵심 부분입니다.
하드웨어와 직접 상호작용합니다.
 

커널 스레드 생성 방법

운영체제는 일반적으로 API난 시스템 호출을 통해 스레드를 생성합니다.
생성된 커널 스레드는 스케줄러에 의해 관리되며 CPU 시간을 할당받아 실행됩니다.

  • 리눅스는 clone() 시스템 호출을 사용하여 커널 스레드를 생성합니다.
  • 스레드가 실행할 함수와 스택 등을 지정하여 새 스레드를 생성합니다.

 

객체 스레드 생성

객체 스레드 : 고수준 프로그래밍 언어에서 사용되는 스레드입니다.
사용자 공간에서 실행되며 API를 통해 운영 체제의 스레드 기능을 이용합니다.
 
Java 에서 Thread 클래스를 사용하여 스레드를 생성하고 관리합니다.
 

객체 스레드 생성 방법

Thread 클래스의 객체를 생성하고 start() 메소드를 호출하여 스레드를 실행합니다.
스레드가 실행할 작업은 Runnable 인터페이스를 구현하여 정의할 수 있습니다.
 

public class NewThread extends Thread {
    public void run() {
        System.out.println("Thread is running.");
    }

    public static void main(String[] args) {
        NewThread t = new NewThread();
        t.start();  // 스레드 실행
    }
}
반응형

'JVM' 카테고리의 다른 글

JVM_19_스레드 종류  (0) 2024.05.11
JVM_18_Thread 스레드  (0) 2024.05.11
JVM_17_GC 다시 알기 (수정사항)  (0) 2024.05.10
JVM_16_Non Stop-the-World, Incremental Garbage Collection  (0) 2024.05.10
JVM_15_Stop the World 일시적인 정지  (0) 2024.05.10