쓰레드 (Thread)

쓰레드(thread)는 프로그래밍 개념으로, 하나의 프로세스(Process) 내에서 실행되는 작업 흐름을 의미한다. 

쓰레드는 프로세스 내에서 실행되는 최소 단위로 한번에 하나의 코드 라인을 수행한다.

하나의 프로세스 내에서는 여러 개의 쓰레드가 동시에 실행될 수 있다.

즉, 쓰레드는 하나의 프로세스 내에서 여러 개의 실행 흐름을 만들어서, 병렬로 작업을 수행할 수 있도록 해준다.

이 때, 쓰레드 간에는 공유되는 메모리가 있기 때문에, 쓰레드 간의 통신 및 동기화에 주의해야 한다.

쓰레드는 일반적으로 다음과 같은 과정으로 동작한다.

  1. 쓰레드 생성
    • 쓰레드는 프로그램 내에서 생성된다.
    • 쓰레드를 생성하는 함수를 호출하면, 운영체제가 쓰레드를 생성하고 프로세스 내의 쓰레드 목록에 추가한다.
  2. 쓰레드 실행
    • 생성된 쓰레드는 프로세스 내의 다른 쓰레드와 동시에 실행된다.
    • 각 쓰레드는 자신만의 실행 흐름을 갖고 있으며, 이를 제어하는 쓰레드 컨텍스트(Thread Context)가 존재한다.
  3. 쓰레드 종료
    • 쓰레드는 자신의 실행을 마치면 종료된다.
    • 종료된 쓰레드는 운영체제에 의해 정리(clean-up)되며, 프로세스 내의 쓰레드 목록에서도 제거된다.
  4. 쓰레드 간 통신 및 동기화
    • 쓰레드 간에는 공유되는 자원이 있기 때문에, 이를 동시에 접근하면 문제가 발생할 수 있다.
    • 이를 해결하기 위해서는 쓰레드 간에 자원을 동기화하고, 통신하는 방법을 사용해야 한다.

쓰레드는 병렬 처리를 통해 프로그램의 실행 속도를 향상시킬 수 있는 매우 중요한 개념이다.

하지만 쓰레드를 사용할 때에는 다른 쓰레드와의 동기화 문제나 데드락 등의 문제에 대한 고려가 필요하다.


쓰레드 생성 방식

1. 클라이언트로부터 요청이 들어올 때 마다 쓰레드를 생성

이 방식은 동시에 많은 수의 요청을 처리할 수 있는 것이 장점이자 단점이 된다.

 

그 이유는 다른 쓰레드가 지연이 되던 말던 상관없이 쓰레드를 무한대로 생성하여 처리를 할 수 있다는 장점이 있지만

반대로 WAS의 성능의 임계점 이상으로 쓰레드를 생성해 버리면 서버가 사망해버리기 때문이다.

 

또한 쓰레드를 생성하는 것 또한 많은 코스트가 들기 때문에 속도에도 문제가 생긴다.


2. 쓰레드 풀을 생성한 후 클라이언트로부터 요청이 들어올 때 마다 생성해 놓은 쓰레드를 할당

이 방법은 1번에 설명했던 쓰레드를 무한정 생성하는 문제점을 보완한 방법이라고 보면 된다.

  • 쓰레드 풀에 생성 가능한 최대량의 쓰레드를 만들어 놓은 후 요청이 들어올 때마다 하나씩 꺼내서 빌려준다.
  • 요청에 대한 응답을 보낸 후 빌려준 쓰레드는 다시 쓰레드 풀로 반납된다.
  • 쓰레드 풀에 더 이상 할당해 줄 수 있는 쓰레드가 없다면 요청에 대해서 대기를 시키거나 거절응답을 보낼 수 있다.

 

이 방법은 쓰레드를 생성하고 종료하는데 들어가는 자원소모를 줄일 수 있고, 응답시간을 단축 시킬 수 있다.


쓰레드를 동시에 처리하는 멀티 쓰레드는 WAS에서 지원을 해주기 때문에 어플리케이션을 개발할 때는 멀티 쓰레드에 대해서 신경쓰지 않아도 된다.

하지만 멀티쓰레드 환경에서 싱글톤 객체에 대해서는 주의깊게 사용할 필요가 있다.


싱글톤(Singleton)

디자인 패턴 중 하나로, 어떤 클래스에 대해 인스턴스를 오직 하나만 생성하도록 보장하는 방법이다.

싱글톤 패턴을 사용하면, 클래스의 인스턴스를 전역적으로 접근 가능한 곳에서 공유할 수 있어서, 효율적인 자원 관리와 데이터 공유가 가능하다.

일반적으로, 데이터베이스 커넥션, 로그 출력, 환경 설정 등과 같은 곳에서 싱글톤 패턴이 사용되고 있다.

싱글톤 객체를 구현하기 위해서는, 해당 클래스 내부에서 인스턴스를 오직 한 개만 생성하도록 하고, 생성된 인스턴스를 외부에서 접근 가능한 static 메서드를 제공하는 것이 일반적이다.

싱글톤 객체를 구현하는 방법은 다양하지만, 대표적인 방법은 다음과 같다.

  1. Eager initialization
    • 클래스 로딩 시점에 인스턴스를 미리 생성하여, 프로그램이 실행될 때 바로 사용할 수 있도록 하는 방법
  2. Lazy initialization
    • 인스턴스가 필요한 시점에 생성하는 방법
    • 다중 쓰레드 환경에서 안전하게 인스턴스를 생성하기 위해서는, synchronized 키워드나 Double-Checked Locking 등의 방법을 사용
  3. Enum
    • Java 5부터 지원되는 열거형(enum)을 사용하여, 싱글톤 객체를 구현할 수 있다.

싱글톤 객체를 사용할 때에는, 다른 객체와의 충돌을 방지하기 위해 생성자를 private으로 선언하고, 인스턴스를 반환하는 static 메서드를 public으로 제공하는 것이 일반적이다. 또한, 멀티스레드 환경에서 안전하게 동작하도록 구현하는 것이 중요하다.

 

 

출처 : 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술

+ Recent posts