Published on

쓰레드(Thread)

Authors
  • avatar
    Name
    유사공대생
    Twitter

프로세스(process)란?

프로세스란 현재 실행중인 프로그램이다. 즉, 사용자가 작성한 프로그램이 운영체제에 의해 메모리 공간을 할당받아 실행 중인 것을 말한다. 프로세스는 프로그램에 사용되는 데이터와 메모리 등의 자원 그리고 스레드로 구성된다.

쓰레드(Thread)란?

image

쓰레드(Thread)는 프로그램 내에서 실행되는 독립적인 실행 흐름을 말한다. 쓰레드는 프로세스 내에서 동시에 여러 작업을 수행할 수 있도록 도와주는 개념이다. 각각의 쓰레드는 프로그램의 코드, 데이터 및 자원에 대한 독립적인 스택을 가지고 있으며, 동시에 실행될 수 있다.

모든 프로세스에는 한 개 이상의 스레드가 존재하여 작업을 수행한다. 또한, 두 개 이상의 스레드를 가지는 프로세스를 멀티스레드 프로세스(multi-threaded process)라고 한다.

image

지금 현재 사용하고 있는 인텔리제이라는 프로세스도 419개의 쓰레드를 사용하는 멀티 쓰레드 프로세스이다.

쓰레드의 장점

  1. 동시성(Concurrency): 여러 쓰레드를 동시에 실행하여 작업을 병렬로 처리할 수 있다. 이는 시스템의 응답성을 향상시키고, 작업의 처리 속도를 높일 수 있다.
  2. 자원 공유(Shared Resources): 쓰레드는 동일한 프로세스 내에서 실행되므로, 메모리, 파일, 소켓 등의 자원을 공유할 수 있다. 이를 통해 효율적인 자원 활용과 데이터의 실시간 공유가 가능하다.
  3. 경량성(Light weight): 쓰레드는 프로세스 내에서 생성되므로, 프로세스 간의 전환에 비해 오버헤드가 적다. 이로 인해 빠른 생성 및 종료, 작업 단위의 유연성을 제공한다.
  4. 병렬 처리(Parallelism): 멀티 코어 또는 멀티프로세서 시스템에서는 여러 쓰레드가 동시에 실행될 수 있으므로, 병렬 처리를 통해 작업의 처리량을 증가시킬 수 있다.

일반적인 쓰레드의 사용법

  1. 쓰레드 생성(Create Thread): 프로그램에서 쓰레드를 생성하여 실행할 작업을 할당한다. 대부분의 프로그래밍 언어와 운영체제는 쓰레드 생성을 위한 라이브러리 함수 또는 시스템 호출을 제공한다.

  2. 쓰레드 실행(Start Thread): 생성된 쓰레드를 실행한다. 이는 쓰레드가 작업을 시작하고 독립적으로 실행되기 위한 단계이다.

  3. 쓰레드 동작(Execute Thread): 쓰레드는 할당된 작업을 수행한다. 작업은 쓰레드 함수 또는 메서드에 정의되어 있으며, 쓰레드가 이를 순차적으로 실행한다.

  4. 쓰레드 종료(Exit Thread): 쓰레드가 작업을 완료하거나 중단되는 경우, 쓰레드는 종료된다. 종료되는 시점에서 쓰레드는 할당된 자원을 반환하고, 관련된 정리 작업을 수행할 수 있다.

쓰레드를 사용할 때 주의점

  1. 경쟁 상태(Race Condition): 여러 쓰레드가 공유 자원에 동시에 접근하면서 예상치 못한 동작이 발생할 수 있다. 이를 방지하기 위해 적절한 동기화 메커니즘을 사용하여 공유 자원에 대한 접근을 제어해야 한다.

  2. 교착 상태(Deadlock): 두 개 이상의 쓰레드가 서로가 점유한 자원을 기다리는 상태로 빠지면서 작업이 진행되지 않는 상황을 말한다. 교착 상태를 피하기 위해 쓰레드 간의 자원 요청 순서를 조율하거나 타임아웃과 같은 메커니즘을 사용할 수 있다.

  3. 오버헤드: 많은 쓰레드를 생성하면 쓰레드 간의 전환 및 관리에 따른 오버헤드가 발생할 수 있다. 따라서 적절한 쓰레드 개수를 설정하고, 쓰레드 생성 및 소멸에 대한 비용을 고려해야 한다.

  4. 동기화 오버헤드: 동기화 메커니즘을 사용할 때 추가적인 오버헤드가 발생할 수 있다. 따라서 필요한 경우에만 동기화를 사용하고, 동기화 범위를 최소화하여 성능을 개선할 수 있다.

쓰레드 동기화란?

쓰레드 동기화는 여러 쓰레드가 공유 자원에 동시에 접근하는 경우에 발생하는 문제를 해결하기 위해 사용되는 메커니즘이다. 동기화는 쓰레드 간의 실행 순서를 조정하거나 공유 자원의 접근을 제어함으로써 상호작용의 일관성과 안전성을 보장한다. 다양한 쓰레드 동기화 방법이 있으며, 가장 일반적인 방법은 다음과 같다.

  1. 락(Lock) 기반 동기화: 락은 공유 자원에 대한 동시 접근을 제어하는 동기화 기법이다. 락을 획득한 쓰레드만이 해당 자원을 사용할 수 있으며, 다른 쓰레드는 락이 해제될 때까지 대기해야 한다. 일반적으로 락은 크리티컬 섹션(Critical Section)이라고 불리는 공유 자원에 대한 접근 코드 블록을 보호하는 데 사용된다.

  2. 세마포어(Semaphore): 세마포어는 정수형 변수로서 동시 접근을 제어하는 동기화 기법이다. 세마포어는 허용되는 동시 접근 수를 제한하고, 쓰레드는 세마포어를 획득하거나 반납함으로써 자원에 대한 접근을 조정한다. 세마포어는 상호 배제(Mutual Exclusion) 또는 동시 실행 가능한 쓰레드 수 제한 등 다양한 용도로 사용될 수 있다.

  3. 조건 변수(Condition Variable): 조건 변수는 쓰레드가 특정 조건을 만족할 때까지 대기하도록 하는 동기화 기법이다. 조건 변수는 쓰레드 간의 통신을 위해 사용되며, 대기(wait)와 신호(signal) 연산을 통해 상태 변화에 대한 알림과 대기 쓰레드의 깨움을 담당한다.

  4. 원자적 연산(Atomic Operations): 원자적 연산은 쓰레드 간에 여러 단계로 구성된 작업을 원자적으로 처리하여 동시 접근 문제를 해결하는 방법이다. 원자적 연산은 하나의 단일 작업으로 간주되어 다른 쓰레드에 의해 중단되지 않으며, 동시 접근에 대한 안전성을 보장한다.

  5. 뮤텍스(Mutex): 뮤텍스는 락과 유사한 개념으로 공유 자원에 대한 동시 접근을 제어하는 데 사용된다. 락과의 차이점은 뮤텍스는 획득한 쓰레드만이 뮤텍스를 해제할 수 있다는 것이다. 따라서 락보다 더욱 유연한 동기화를 구현할 수 있다.

  6. 리엔트러너트 락(Reentrant Lock): 리엔트러너트 락은 하나의 쓰레드가 이미 획득한 락을 다시 획득할 수 있는 기능을 제공하는 락이다. 이는 동일한 쓰레드에서 중첩된 락 획득이 필요한 경우 유용하다. 리엔트러너트 락은 재진입 가능한 락(Reentrant Lock) 또는 재진입 락(Recursive Lock)이라고도 불린다.

  7. 바리어(Barrier): 바리어는 쓰레드 그룹이 특정 지점에서 모두 도착할 때까지 대기하는 동기화 기법이다. 쓰레드들은 바리어를 통과하기 전에 대기하며, 모든 쓰레드가 도착하면 동시에 실행을 재개한다. 이를 통해 쓰레드들 간의 동기화 및 작업 단계별 동기화를 구현할 수 있다.

  8. Read-Write Lock: Read-Write Lock은 공유 자원에 대한 동시 읽기 접근은 허용하고, 쓰기 접근은 상호 배제하는 동기화 기법이다. 이는 읽기 작업이 서로 간섭하지 않고 병렬로 실행될 수 있도록 하며, 쓰기 작업은 독점적으로 실행된다.

이러한 쓰레드 동기화 기법들은 프로그램의 요구 사항과 동시 접근 상황에 맞게 선택되고 사용되어야 한다. 동기화 기법의 올바른 선택은 쓰레드 간의 안전한 상호작용과 성능을 보장하는 데 중요한 역할을 한다.

참고자료