[Java] 강의를 복습하면서...(4)

석연걸·2025년 1월 6일

스파르타 코딩클럽

목록 보기
6/17

프로세스 : OS로부터 자원을 할당받는 작업의 단위

  • 실행 중인 프로그램을 의미

  • 예시 : 우리가 Java 프로그램을 실행시키면 이 프로그램은 프로세스라는 이름으로 OS 위에서 실행됨

  • 구조 : OS가 프로그램 실행을 위한 프로세스를 할당해 줄 때 프로세스 안에 Code, Data, Memory(Stack, Heap) 을 같이 할당해준다.

    • Code : Java의 main 메소드와 같은 코드를 말함
    • Data : 프로그램이 실행 중 저장할 수 있는 저장 공간
      • 전역변수, 정적변수, 배열 등 초기화된 데이터를 저장하는 공간
    • Memory(메모리 영역)
      • Stack : 지역변수, 매개변수, 리턴변수를 저장하는 공간
      • Heap : 동적으로 필요한 변수를 저장하는 공간( new() )


쓰레드 : 프로세스가 할당받은 자원을 이용하는 실행의 단위

  • 프로세스내에서 일하는 일꾼(코드실행의 흐름)
  • 생성 : 프로세스가 작업중인 프로그램에서 실행 요청이 들어오면 쓰레드를 만들어 명령을 처리
  • 프로세스 안에는 여러 쓰레드가 있고, 쓰레드들은 실행을 위해 메모리 공간(Heap)을 공유받는다.
  • 쓰레드들은 명령 처리를 위해 자신만의 메모리 공간(Stack)도 할당받는다.
  • Java 쓰레드 : JVM 프로세스 안에서 실행되는 쓰레드이며, JVM에 의해 Java Main 쓰레드부터 실행됨

싱글 쓰레드 : 프로세스 안에서 하나의 쓰레드만 실행되는 것

  • Java에서 main() 메서드만 실행시켰을 때 이것을 싱글 쓰레드라고 함
  • Java에서 main() 메서드의 쓰레드를 "메인 쓰레드"라고 부른다
  • JVM의 메인 쓰레드가 종료되면, JVM도 같이 종료된다

멀티 쓰레드 : 프로세스 안에서 여러 개의 쓰레드가 실행되는 것

  • 하나의 프로세스가 여러 개의 쓰레드를 가질 수 있으며, 이 쓰레드들은 프로세스의 자원을 공유
  • Java는 메인 쓰레드 외에 다른 작업 쓰레드를 생성해 여러 개의 실행 흐름을 만들 수 있다
  • 장점
    • 여러 개의 쓰레드를 통해 여러 작업을 동시에 해서 성능이 좋다
    • Stack을 제외한 모든 영역에서 메모리를 공유해 자원을 효율적으로 사용할 수 있음
    • 응답 쓰레드와 작업 쓰레드를 분리해 빠르게 응답을 줄 수 있음(비동기)
  • 단점
    • 동기화 문제가 발생할 수 있음 (자원을 공유하면서 작업을 처리하기 때문에 서로 자원을 사용하려는 충돌이 발생 가능)
    • 교착 상태에 걸릴 수 있음 (서로의 자원을 원하는 상태가 되어 상대의 작업의 종료를 계속 기다리는 상태)

데몬 쓰레드

  • BackGround에서 실행되는 낮은 우선순위를 가진 쓰레드 (대표적으로 가비지 컬렉터가 있음)
  • 다른 쓰레드가 모두 종료되면 데몬 쓰레드는 강제 종료를 당함

사용자 쓰레드

  • ForeGround에서 실행되는 높은 우선순위를 가진 쓰레드 (대표적으로 메인 쓰레드가 있음)
  • JVM은 사용자 쓰레드의 작업이 끝나면 데몬 쓰레드도 자동으로 종료시켜 버린다.

쓰레드 우선순위

  • 쓰레드 작업의 중요도에 따라서 쓰레드의 우선순위를 부여할 수 있음
  • 쓰레드는 생성될 때 우선순위가 정해지는데, 이 우선순위는 우리가 직접 지정하거나 JVM에 의해 지정될 수 있음
  • setPriority(1~10) : 메서드로 우선순위 설정 가능 (1~10 숫자가 클수록 우선순위가 높음)

쓰레드 그룹

  • 서로 관련이 있는 쓰레드들을 그룹으로 묶어서 다룰 수 있음
  • 모든 쓰레드들은 반드시 하나의 그룹에 포함되어 있어야 하며, 기본적으로 그룹에 포함되어 있음
  • interrupt() : 일시정지 상태인 쓰레드를 실행 대기 상태로 변경

쓰레드 상태

  • 쓰레드 객체가 생성되고 start() 메서드를 통해 실행 대기로 이동

  • 쓰레드는 실행과 대기를 반복하며 run() 메서드를 수행한다.

  • run() 메서드가 종료하면 실행이 멈춤

  • 일시정지 상태에서는 쓰레드가 실행할 수 없는 상태가 됨

  • 쓰레드가 다시 실행 상태로 넘어가기 위해서는 일시정지 -> 실행대기(interrupt()) 상태로 넘어가야 됨

쓰레드 제어

  • sleep() : 현재 쓰레드를 지정된 시간동안 멈추게 함 (반드시 InterruptedException 예외처리 해줘야됨)

  • interrupt() : 일시정지인 상태를 실행 대기 상태로 만듦

  • join() : 정해진 시간동안 지정한 쓰레드의 작업을 기다림 (시간을 지정하지 않았으면 그 쓰레드의 작업이 끝날 때 까지 기다림, sleep()과 같은 예외처리)

  • yield() : 남은 시간을 다른 쓰레드에게 양보하고 자신은 실행 대기 상태가 됨

  • synchronized(동기화) : 한 쓰레드가 진행중인 작업을 다른 쓰레드가 침범하지 못하게 함

    • 임계 영역 : 하나의 쓰레드만 출입이 가능하도록 만든 영역
  • wait() : 하나의 쓰레드가 작업을 진행하다가 wait()을 호출하면 Lock을 반납하고 해당 객체의 대기실에서 대기함

  • notify() : 해당 객체의 대기실에 있는 모든 쓰레드 중 임의의 쓰레드를 호출 (그 쓰레드는 다시 Lock을 받음)

  • Lock : Synchronized 블럭으로 동기화하면 자동으로 Lock이 걸리고 풀리지만, 같은 메서드 내에서만 Lock을 걸 수 있음 (이런 제약의 해결을 위해 사용)

    • ReentrantLock : 재진입 가능한 Lock이며, 특정 조건에서 Lock을 풀고 나중에 다시 Lock을 얻어 임계 영역으로 진입
    • ReentrantReadWriteLock : 읽기와 쓰기를 위한 Lock을 따로 제공하며, 읽기는 공유적이고 쓰기는 배타적이다
    • StampedLock : ReentrantReadWriteLock + 낙관적인 Lock(데이터 변경 전 Lock을 걸지 않는 것)
  • Condition : wait() & notify()의 문제점인 대기실 내 쓰레드를 구분하지 못한다는 것을 해결한 인터페이스

    • java.util.concurrent.locks 패키지 내에서 Condition 인터페이스와 ReentrantLock 클래스를 제공
    • wait() & notify() 대신 Condition의 await() & signal()을 사용

0개의 댓글