2 minute read

📖 쓰레드

멀티 쓰레드 프로그래밍이란 하나의 응용 프로그램에서 동시에 여러 처리를 하기 위해 쓰레드를 생성하여 운영하는 프로그램이다.
자바에서는 이를 지원하기 위하여 2가지 방법을 지원하는데, Thread 클래스를 상속받거나, Runnable 인터페이스를 구현하는 것이 있다.


🍄 Thread 클래스

Thread 클래스 를 상속 받은 후, run() 함수를 오버라이딩 한다.
이후, run() 메소드를 호출하면, JVM에서 새로운 쓰레드로 실행한다.
따라서, 다른 클래스를 추가적으로 상속 받을 수 없기 때문에, 일반적으로 Runnable 인터페이스를 구현하여 스레드를 사용한다.

public class Main {

    public static void main(String[] args) {
        PrintOne thread1 = new PrintOne(1000);
        PrintOne thread2 = new PrintOne(1000);

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

class PrintOne extends Thread{
    private int times;

    public PrintOne(int times){
        this.times = times;
    }

    @Override
    public void run(){
        for (int i = 0; i < times; i++) {
            System.out.println(1);
        }
    }
}

start()run()의 차이

  • run()은 스레드 객체를 실행하는 것이 아닌, 클래스 내부의 run() 메소드를 실행시키는 것이다.


🍄 Runnable 인터페이스

Runnable interface를 구현하여 익명 구혁 객체나 구현 클래스로 구현하여 사용한다.
다른 class의 상속을 받을 수 있기 때문에, 주로 쓰레드 사용시에는 Runnable 인터페이스를 사용한다.

public class Main {

    public static void main(String[] args) {
        Runnable printTwo = new PrintTwo(1000);
        
        Thread thread1 = new Thread(printTwo);
        Thread thread2 = new Thread(printTwo);

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

class PrintOne implements Runnable{
    private int times;

    public PrintNum(int times){
        this.times = times;
    }

    @Override
    public void run(){
        for (int i = 0; i < times; i++) {
            System.out.println(2);
        }
    }
}


📖 쓰레드의 상태

  • 객체 생성 (NEW) : start() 메소드가 호출되지 않은 상태로 스레드 객체를 생성.
  • 실행 대기 (RUNNABLE) : 실행을 대기하는 상태, 언제든 실행 상태로 갈 수 있음.
  • 일시 정지 (WAITING) : 다른 스레드가 통지할 때까지 기다리는 상태
  • 일시 정지 (TIMED_WAITING) : 주어진 시간동안 기다리는 상태
  • 일시 정지 (BLOCKED) : 동기화로 인해 사용하고자 하는 객체의 락이 풀릴 때까지 기다리는 상태

이는 Thread 클래스의 getState() 메서드로 확인이 가능하다.

image


📖 쓰레드의 우선순위

자바는 쓰레드 스케줄러가 스레드의 우선 순위에 따라 스레드에 프로세서를 할당한다.
1-10으로 구성되어 있으며 기본적으로 쓰레드 실행시 5로 설정된다.
setPriority 메소드를 사용하여 우선순위를 조정가능하다.


📖 Main의 종류

자바에서 main 함수는 크게보면, 하나의 쓰레드라고 할 수 있다.
따라서, 자바에는 main 쓰레드, sub 쓰레드, Daemon 쓰레드 3가지가 있다.

  • main 쓰레드
    • main() 메소드가 실행이 되는 곳으로 프로세스가 실행되면 가장 먼저 실행
    • 싱글 스레드 프로세스에서는 main() 함수가 종료되면 프로세스가 종료
  • sub 쓰레드
    • 멀티 쓰레드 프로세스의 경우 모든 쓰레드가 종료되야 프로세스가 종료된다.
  • Daemon 쓰레드
    • 주 스레드의 작업을 돕는 보조적인 역할을 수행하는 스레드


📖 동기화 (Synchronized)

동기화멀티 쓰레드 프로그램에서 여러 스레드가 하나의 공유자원에 접근하려 할 때, 자원을 보호하기 위해서 사용한다.
일반적으로 unlocklock 기능을 통해 자원 공유를 막으며 Mutex, Semaphore가 존재한다.

📖 교착상태 (DeadLock)

교착상태란 두 개 이상의 작업이 서로 상대방의 작입이 끝나기 만을 기다리고 있기 때문에, 결과적으로 아무것도 완료되지 않는 상태이다.
교착상태가 발생하기 위해서는 다음 4가지 조건을 모두 만족해야 한다.


🍄 코프만 조건 (Coffman condition)

  • 상호 배제 (Mutual Exclusion)
    • 각 자원은 한 번에 하나의 스레드에게만 할당
  • 소유 대기 (Hold & Wait)
    • 스레드가 한 자원을 소유하면서 그 자원을 반납하지 않고 다른 자원을 기다리기
  • 강제 자원 반환 불가 (No Preemption) → 비선점 조건
    • 스레드에게 할당된 자원을 강제로 빼앗지 못함
  • 환형 대기 (Circular Wait)
    • 한 그룹의 스레드들에 대해, 각 스레드는 다른 스레드가 요청하는 자원을 소유하는 환형 고리 형성

위의 4가지가 모두 성립한다고 반드시 교착상태가 발생하는 것은 아니다.


🍄 교착 상태 해결 방법

  • 예방(prevention) → 비현실적 방법
  • 회피(avoidance) → 비현실적 방법
  • 감지 및 복구(detection and recovery) → 가능은 하나 CPU 부담이 큰 방식
  • 무시 → 현실적 방법

-> 대부분의 운영체제에서는 타조(Ostrich) 알고리즘을 사용한다.



개인 공부 기록용 블로그입니다.
틀리거나 오류가 있을 경우 제보해주시면 감사하겠습니다.😁