티스토리 뷰

프로세스와 스레드

프로세스 ( Process )

  • 자신만의 메모리 영역을 가지고, 작업을 처리하는 동적인 프로그램.

 

 

스레드 ( Thread )

  • 프로세스 내부에서 작업을 나누어 처리하는 작은 프로세스로, 자신만의 메모리와 프로세스 내부의 스레드가 공유하는 공유 메모리를 가지고 작업을 처리한다.

 

 

동시성 문제

 

예상하는 순서및 결과

  1. 스레드 01 이 공유 데이터 a = 1 저장
  2. 스레드 01 가 pring(a) 를 통해 콘솔에 1를 출력함
  3. 스레드 02 이 공유 데이터 a = 2 저장
  4. 스레드 02 가 pring(a) 를 통해 콘솔에 2를 출력함

 

실제 동작될 수 있는 예

  1. 스레드 01 이 공유 데이터 a = 1 저장
  2. 스레드 02 이 공유 데이터 a = 2 저장
  3. 스레드 02 가 pring(a) 를 통해 콘솔에 2를 출력함
  4. 스레드 01 가 pring(a) 를 통해 콘솔에 2를 출력함

스레드의 실행 순서는 보장할 수 없다보니, 공유 데이터를 수정하는 작업이 진행되면 여러 스레드가 동시 작업을 할 때 예상치 못한 결과가 발생할 수 있다. 이런 경우를 동시성 문제 라고한다.

 

 

Synchronized 사용하기.

동시성 문제를 해결하기 위해서 어떻게 해야할까?

  • 바로 synchronized 를 사용하는 것이다.

 

Synchronized 사용 방법

자바 에서는 이러한 멀티스레딩에서 동시성 문제를 해결하기 위해, 모니터 락 을 사용하고 있다.

모니터(Monitor) 와 락(Lock)은?

  • 하나의 객체에 하나의 모니터가 결합되어 있는데, 이러한 모니터는 결합된 객체에 두 개의 스레드가 동시 접근을 할 수 없고 락(Lock)을 가진 스레드만 접근할 수 있도록 막는 역할을 진행한다.
  • 이 락을 가진 스레드만 접근할 수 있는 영역, 모니터가 감시하고 있는 영역을 임계 영역(Critical Section) 이라고 하며 Synchronized 는 자바에서 이러한 임계 영역과 모니터를 지정해주는 키워드.

[사용 방법]

 

 

DeadLock ( 교착 상태 )

DeadLock 해석하면 Lock 이 죽었다는 의미이고, 한국에서는 교착 상태라고 부른다. 이를 쉽게 해석하면 아래와 같다.

 

 

교착상태?

한국에서 DeadLock 을 교착 상태라고 부르는 이유가 있다. 특정 임계 영역에는 Lock 을 가진 하나의 스레드만 접근 가능한데, 두 스레드의 작업에 필요한 Lock 을 서로가 들고 있을 때 서로 Lock을 놓아주지 않아 무한정으로 대기하고 있는 상태를 얘기한다.

 

 

해결 방법

  1. 각각의 스레드가 공유 데이터를 사용하지 않아 락이 필요하지 않도록 한다.
    1. Stateless 유지
      1. 상태 변수를 읽기 전용으로 유지한다. ( final 사용 )
      2. 로컬 변수를 사용한다.
  2. 각각의 스레드가 무한정 대기하지 않도록 TimeOut 을 걸어둔다.

JVM 메모리내 공유하는 영역 VS 공유하지 않는 영역

 

자바의 공유 메모리 영역

  • 메서드 영역
    • 메서드, static 변수, 클래스 주소등을 가지고 있는 영역
  • 힙 영역
    • 인스턴스가 생성되는 영역.

 

 

자바의 스레드별 독립적인 메모리 영역

  • 스택 영역
    • 메서드 호출시 각 블록(스택프라임)이 쌓이는 영역
    • 로컬 변수등은 각 스택 프라임에 생성된다.
  • Native 스택 영역
    • JNI를 통해 Native Method가 호출되어 쌓이는 영역
  • PC(Program Count) Register
    • 스택이 실행하고 있는 위치를 기록하고 있다.

그래서?

  • DeadLock을 발생시키지 않는 가장 좋은 방법은 락을 사용하지 않는 것이다. 그를 위해서는 공유 메모리 영역을 사용하는 경우에는 언제나 스레드 안전성을 고려해야 한다. 공유 데이터는 읽기 전용으로 Stateless 하게 구성하고, 독립적인 영역은 마음껏 사용하자.

 

로컬 변수로 오브젝트 사용 시?
인스턴스는 분명히 힙 영역에 존재하지만, 그 힙 영역을 참조할 수 있는 변수는 스택 영역에 존재하기 때문에 그 범위를 벗어나면 GC에 청소 대상이된다. 따라서 공유될 수 있는 영역에 있는 것은 사실이지만 실질적으로 공유할 수 없다.
댓글