Thread

U·2022년 9월 5일
0

Java

목록 보기
4/4

프로세스 스케줄링

  • 선점형(Preemptive)
    : 대기중인 프로세스가 갖는 컴퓨터의 자원(CPU 사이클)을 우선적으로 차지할 수 있는 권한
  • 비선점형(Non-Preemptive)
    : 프로세스가 자발적으로 자원을 반납하기 전까지는 CPU 사용권이 넘어가지 않음

스케줄링 알고리즘

FCFS(First Come First Serve)

  • 비 선점형 스케줄링 기법으로 먼저 도착한 순서에 따라 처리
  • 프로세스의 처리 시간이 길 경우, 대기 프로세스의 대기 시간이 길어지는 단점

SJF(Shortest Job First)

  • 비 선점형 스케줄링 기법으로 실행 시간이 가장 짧은 순서대로 처리
  • 실행 시간이 긴 프로세스는 계속 밀림 -> 무한 대기가 발생할 수 있음

HRN(Highest Response-ratio Next)

  • 비 선점형 스케줄링 기법으로 SJF에서 발생할 수 있는 무한대기 문제를 해결한 기법
  • 시스템 응답 시간이 큰 프로세스 우선 처리

Priority Scheduling

  • 선점형/ 비 선점형 스케줄링 기법으로 특정 규칙에 따라 우선순위를 매겨서 실행시킴
  • 비선점형의 경우 우선 순위가 낮으면 무한 대기가 발생할 수 있음
  • 선점형의 경우 실행에 따라 조건이 변경되어 우선 순위가 높아진 프로세스가 프로세서를 빼앗아 올 수 있음

Round Robin Scheduling

  • 선점형 스케줄링 기법으로 프로세스의 종료 여부와 관계 없이 일정 시간 간격으로 돌아가면서 모든 프로세스가 실행됨
  • 프로세스 전환 시간이 짧으면 오버헤드가 많아지는 단점이 있음

Java에서 스레드를 구현하려면?

첫번째 방법. Thread 클래스 상속 : 자바에서는 클래스의 다중 상속을 지원하지 않으므로 다른 클래스의 상속이 불가능하다🙄 But 객체 생성 후 바로 실행 가능하다는 장점이 있다!
이때, Thread 클래스를 상속하면 run() 메소드를 꼭 오버라이딩 해줘야한다.

두번째 방법. Runnable 인터페이스 : 다른 클래스에서 상속을 통해 구현 가능하나 객체 생성 후 바로 사용할 수 없고 추가적인 Thread 객체가 요구된다.
Ex) TestThread test = new TestThread("test");
Thread thread = new Thread(test);


단일 스레드

  • Main 스레드에서 작업 진행, 작업은 순차적으로
  • 하나의 프로세스에서 오직 하나의 스레드로만 실행
    : 단일 레지스터와 스택으로 구성
  • Context Switching 작업을 요구하지 않음
  • 동시성 제어에 대한 처리 신경쓰지 않아도 됨

멀티 스레드

  • 프로그램 내에서 두 개 이상의 동작을 동시에 실행
    : 프로세서의 활동 극대화, 두 개가 동작을 동시에 실행
    ✔ 이때 말하는 동시는 우리가 흔히 생각하는 동시가 아니다. 그럼 무엇일까?
    (내가 생각하는 이유로는) 멀티 스레드에서 짧은 시간동안 번갈아가면서 동작을 하기 때문에 동시에 이루어지지 않지만 우리가 겉에서 볼 땐 동시에 동작하는 것처럼 보이기도 한다.

Thread 상태

  • New
    스레드가 실행 준비를 완료한 상태로, start() 메소드를 호출하기 전 상태
  • Runnable
    start()가 호출되어 실행될 수 있는 상태
  • Wait
    다른 스레드가 통지할 때까지 기다리는 상태
  • Timed_Wait
    정해진 시간동안 기다리는 상태
  • Blocked
    사용하고자 하는 객체의 잠금(lock)이 풀릴 때까지 대기하는 상태
  • Terminated
    실행이 종료된 상태

외부에서 스레드 상태 변경을 위한 메소드

interrupt() 메소드

  • 스레드가 일시 정지 상태에 있을 때, InterruptException 예외를 발생시키는 역할
  • sleep()이 있을때만 사용할 수 있음

wait() 메소드

  • 동기화 영역에서 lock을 풀고 Wait-Set 영역으로 이동
  • lock을 소유한 스레드가 자신의 제어권을 양보하고 WAITING 또는 TIMED_WAITING 상태에서 대기하기 위해서 사용

notify(), notifyAll() 메소드

  • notify()는 하나, notifyAll()은 Wait-Set 영역에 있는 전부를 깨운다.
  • notify()는 Wait-Set 영역에서 대기중인 스레드중 랜덤하게 깨움
  • notify()를 사용하면 synchronized를 써줘야 실행된다.
  • notifyAll()을 사용하게 되면 synchronized에서는 하나만 실행할 수 있으므로 실행되지 않는 나머지는 Blok 상태가 된다.

sleep(long millis), sleep(long millis, int nanos) 메소드

  • 지정된 시간 동안 쓰레드 일시 정지
  • 지정된 시간이 지나고 나면 다시 실행 상태
  • interrupt가 걸리기 위한 조건으로 interrupted()를 사용하여 체크(sleep이 없으면 interrupt이 걸리지 않는 것을 확인하기 위해 busy waiting을 사용)

join() 메소드

  • join() : 호출한 스레드가 종료될 때까지 기다림
  • join(long millis) : 호출한 스레드를 지정된 시간동안만 기다림
  • join(long millis, int nanos) : 호출한 스레드를 지정된 시간동안 기다림, 대기 시간은 나노초 단위로 제어
    Ex) thread1.join();

yield() 메소드

  • static 메소드
  • 현재 실행 중인 스레드를 중지시켜 동일한 우선 순위의 다른 대기 스레드를 동작시킬 수 있음 -> 동일한 우선 순위가 없는 경우, 다시 실행
  • 하나의 스레드가 프로세서를 과도하게 점유하지 않도록 조절

Thread 동기화(synchronized)

  • 동기화는 연산이 겹치면 안되는 부분에 사용한다.

첫번째 방법. 메소드 동기화(메소드 전체)

public synchronized void 메소드() { 내용.. }

두번째 방법. 구간 동기화(특정 구간만)

public void 메소드() {
	내용..
    synchronized (this) {
    	동기화 할 내용..
    }
}

임계구역(Critical Section)

  • 병렬 컴퓨팅에서 두 이상의 스레드가 동시에 접근해서는 안되는 공유 자원을 접근하는 코드의 일부
  • 공유 데이터를 사용하는 코드 영역을 임계구역으로 지정해놓고 공유 데이터(객체)가 가지고 있는 lock을 획득한 단 하나의 스레드만 이 영역 내의 코드를 수행할 수 있게 한다. 그리고 해당 스레드가 임계구역 내의 모든 코드를 수행하고 lock반납해야 다른 스레드가 반납된 lock을 획득하여 임계구역의 코드를 수행할 수 있게 된다.
profile
백엔드 개발자 연습생

0개의 댓글