Fundamentals/Computer Science

[운영체제] 자바의 스레드와 멀티스레드 기본 개념

dev seon 2025. 1. 21. 23:26

 

01 서론

운영체제에 대해 공부하며 CPU 성능과 자원 활용에 관심을 가지게 되었습니다.

특히, 기술의 발전으로 코어가 여러 개인 프로세서 환경에서 CPU의 활용에 따라 프로그램 성능이 달라질 수 있다는 점에 주목했습니다.

자바에서 스레드와 멀티스레드는 프로그램의 성능을 향상시키고, 효율적인 작업 처리를 가능하게 하는 중요한 개념입니다.

이 글에서는 자바의 스레드와 멀티스레드의 기본 개념을 정리하고 실제로 이를 어떻게 활용하는지 예시 코드를 작성해보았습니다.

02 스레드와 멀티스레드의 기본 개념

1. 프로세스란 무엇인가?

먼저, 프로세스란 CPU에 의해 메모리에 올려져 실행중인 프로그램을 의미하고 독립적인 실행 환경을 가진다는 특징이 있습니다.

자바 JVM은 하나의 프로세스로 실행이 되지만, 여러 작업을 동시에 처리하기 위해 멀티 스레드도 지원합니다.

2. 스레드란 무엇인가?

프로세스 내에서 실행되는 최소 단위의 작업 흐름

스레드는 프로세스 안에서 작업을 실행하는 단위로 자바의 JVM에 의해 관리됩니다.

각 스레드는 독립적인 실행 흐름을 가지며, 하나의 프로그램 내에서 여러 스레드를 동시에 실행할 수 있습니다.

스레드는 프로그램 내에서 다양한 작업을 병렬로 처리하는 데 유용합니다.

3. 멀티스레드란 무엇인가?

두 개 이상의 스레드를 동시에 실행하는 프로그래밍 기법

멀티스레드를 사용하면 여러 작업을 동시에 처리할 수 있어 프로그램의 성능을 크게 향상시킬 수 있습니다.

자바에서는 멀티스레드를 구현할 수 있는 다양한 방법과 도구를 제공합니다.

03 자바에서 스레드 만들기

1. Thread 클래스와 Runnable 인터페이스

자바에서 스레드를 만들려면 두 가지 방법이 있습니다.

  • Thread 클래스 상속
    class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("스레드 실행 중...");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            MyThread thread = new MyThread();
            thread.start();
        }
    }
    
  • Thread 클래스를 상속받고, run() 메서드를 오버라이드하여 스레드를 실행할 작업을 정의할 수 있습니다.
  • Runnable 인터페이스 구현이 방법은 Thread 클래스 상속이 제한될 때 유용합니다.
  • class MyRunnable implements Runnable { @Override public void run() { System.out.println("스레드 실행 중..."); } } public class Main { public static void main(String[] args) { Thread thread = new Thread(new MyRunnable()); thread.start(); } }
  • Runnable 인터페이스를 구현한 클래스를 사용하여 스레드를 만들 수도 있습니다.

2. 스레드 제어 메서드

  • start(): 스레드를 시작합니다.
  • run(): 스레드가 실행할 작업을 정의합니다.
  • sleep(): 일정 시간 동안 스레드를 일시 정지시킵니다.
  • join(): 현재 스레드가 다른 스레드가 종료될 때까지 기다리도록 합니다.

04 멀티스레드 프로그래밍

1. 스레드 안전성

멀티스레드 환경에서는 여러 스레드가 동일한 자원에 접근할 수 있기 때문에, 스레드 안전성 문제가 발생할 수 있습니다.

이러한 문제를 해결하려면 스레드 간 동기화가 필요합니다.

2. synchronized 키워드

자바에서는 synchronized 키워드를 사용하여 메서드나 블록을 동기화할 수 있습니다.

이 키워드는 한 번에 하나의 스레드만 해당 코드 블록을 실행하도록 보장합니다.

public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}

3. 동기화 문제 해결

멀티스레드 환경에서 데드락과 같은 문제도 발생할 수 있습니다.

데드락이란 운영체제나 소프트웨어에서 둘 이상의 프로세스 또는 스레드들이 아무것도 진행하지 않은 상태로 대기하는 상태로, 한국말로 교착상태라고도 합니다.

이를 피하기 위해선 자원을 올바르게 관리하고, 적절한 동기화 전략을 사용해야 합니다.

05 멀티스레드를 활용한 간단한 프로그램

다음은 자바에서 멀티스레드를 활용해 동시에 작업을 처리하는 프로그램입니다.

public class Main {
    public static void main(String[] args) {
        Runnable task1 = () -> {
            System.out.println("Task 1 시작");
            try { Thread.sleep(1000); } catch (InterruptedException e) {}
            System.out.println("Task 1 종료");
        };

        Runnable task2 = () -> {
            System.out.println("Task 2 시작");
            try { Thread.sleep(1000); } catch (InterruptedException e) {}
            System.out.println("Task 2 종료");
        };

        Thread thread1 = new Thread(task1);
        Thread thread2 = new Thread(task2);

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

이 예제에서는 두 개의 작업이 동시에 실행되고 각 스레드는 1초 동안 대기한 후 종료됩니다.

06 결론

자바에서 스레드와 멀티스레드는 프로그램의 성능을 높이고, 복잡한 작업을 동시에 처리하는 데 중요한 역할을 합니다.

스레드를 올바르게 사용하면 프로그램이 효율적으로 동작하고, 멀티코어 CPU의 성능을 최대한 활용할 수 있습니다.

그러나 동기화 문제나 성능 최적화와 같은 과제가 따르므로, 이를 잘 관리하는 것이 중요합니다.

아직까지 프로젝트에서 스레드를 직접 활용해본 적은 없지만 CPU 성능을 활용해 최적화를 할 때 적용해보고 싶습니다.