개발/VC++

[스크랩] 쓰레드란?

99iberty 2021. 7. 7. 17:32

스레드(thread)란 프로세스(process) 내에서 실제로 작업을 수행하는 주체를 의미합니다.

모든 프로세스에는 한 개 이상의 스레드가 존재하여 작업을 수행합니다.

  • 쓰레드란 프로그램(프로세스) 실행의 단위이며
    하나의 프로세스는 여러개의 쓰레드로 구성이 가능하다.
  • 하나의 프로세스를 구성하는 쓰레드들은 프로세스에 할당된 메모리, 자원 등을 공유한다.

사전적 의미
“프로세스 내에서 실행되는 여러 흐름의 단위”
프로세스의 특정한 수행 경로
프로세스가 할당받은 자원을 이용하는 실행의 단위

 

쓰레드(Thread)란 간단히 말해 프로세스 내에서 실행되는 실행 단위이다. 프로세스는 이러한 쓰레드를 한 개 이상으로 나눌 수 있다. 쓰레드는 프로그램 카운터와 스택 포인터 등을 비롯한 쓰레드 실행 환경 정보(Context 정보), 지역 데이터, 스택을 독립적으로 가지면서 코드, 전역 데이터, 힙을 다른 쓰레드와 공유한다.

 

 

https://coding-start.tistory.com/199

 

운영체제 - 쓰레드란?(Thread,사용자 수준 쓰레드, 커널 수준 쓰레드, 혼합형 쓰레드)

2019/07/27 - [운영체제] - 운영체제 - 프로세스(Process)란? 프로세스상태,Context Switching 운영체제 - 프로세스(Process)란? 프로세스상태,Context Switching 프로세스의 개념 프로세스는 다양한 정의가 있다...

coding-start.tistory.com

운영체제 - 쓰레드란?(Thread,사용자 수준 쓰레드, 커널 수준 쓰레드, 혼합형 쓰레드)

2019/07/27 - [운영체제] - 운영체제 - 프로세스(Process)란? 프로세스상태,Context Switching

 

운영체제 - 프로세스(Process)란? 프로세스상태,Context Switching

프로세스의 개념 프로세스는 다양한 정의가 있다. 실행 중인 프로그램 비동기적 행위 실행 중인 프로시저 실행 중인 프로시저의 제어 추적 운영체제에 들어 있는 프로세스 제어 블록(PCB) 프로세서에 할당하여 실..

coding-start.tistory.com

 

쓰레드(Thread)란 간단히 말해 프로세스 내에서 실행되는 실행 단위이다. 프로세스는 이러한 쓰레드를 한 개 이상으로 나눌 수 있다. 쓰레드는 프로그램 카운터와 스택 포인터 등을 비롯한 쓰레드 실행 환경 정보(Context 정보), 지역 데이터, 스택을 독립적으로 가지면서 코드, 전역 데이터, 힙을 다른 쓰레드와 공유한다.

그림을 보면 프로세스 내에서 쓰레드는 별도의 Stack(+ 스레드 실행 환경 정보, 지역데이터, 레지스터 등)을 할당받고 Code, Data, Heap 영역은 같은 프로세스 내의 다른 쓰레드와 공유한다.

 

프로세스 하나에 포함된 쓰레드들은 공동의 목적을 달성하려고 병렬로 수행한다. 이러한 쓰레드를 이용하면 아래와 같은 이점들이 있다.

  • 사용자 응답성 증가
  • 프로세스 자원과 메모리 공유가능
  • 경제성이 좋음(프로세스 컨텍스트 스위칭보다 쓰레드 컨텍스트 스위칭이 오버헤드가 더 적다.)
  • 다중 처리로 성능과 효율 향상

현대 시스템은 대부분 다중 쓰레드 운영체제이다. 다중 쓰레드는 프로그램 하나를 여러 실행 단위로 쪼개어 실행한다는 측면에서 다중 처리(다중 프로세싱)와 의미가 비슷하다. 하지만 동일 프로세스의 쓰레드는 자원을 공유하므로 자원 생성과 관리의 중복성을 최소화하여 실행 능력을 향상시킬 수 있다. 그리고 각 쓰레드는 커널이 개입하지 않고도 독립적으로 실행할 수 있어 서버에서 많은 요청을 효과적으로 처리할 수 있다.

 

이러한 쓰레드의 특성 때문에 프로세스보다 쓰레드를 생성하는 것이 더 빠르고, 동일한 프로세스에 있는 쓰레드 간의 교환이나 쓰레드 종료도 훨씬 빠르다.

 

보통 프로세스를 생성하면 해당 프로세스의 쓰레드도 함께 생성한다. 단, 쓰레드 생성에서는 운영체제가 부모 프로세스와 공유할 자원을 초기화할 필요가 없다. 해당 프로세스가 스택과 레지스터를 직접 제공하기 때문이다. 그러므로 프로세스의 생성과 종료보다는 오버헤드가 훨씬 적다. 여기서 스레드의 장점 하나는 쓰레드 한개가 대기 상태로 변할 때 전체 프로세스를 대기 상태로 바꾸지 않는다는 것이다. 실행 상태의 쓰레드가 대기 상태가 되면 다른 쓰레드를 실행할 수 있다. 그러나 프로세스와 달리 서로 독립적이지는 않다. 프로세스 하나에 있는 전체 쓰레드는 프로세스의 모든 주소에 접근할 수 있으므로 쓰레드 한 개가 다른 쓰레드의 스택을 읽거나 덮어쓸 수 있다.

 

쓰레드 제어 블록(TCB)

프로세스가 프로세스 제어 블록에 정보를 저장하듯이 쓰레드도 쓰레드 제어 블록에 정보를 저장한다. 그런데 프로세스는 쓰레드를 한 개 이상 가질수 있으므로, 결국 프로세스 제어블록은 스레드 제어 블록의 리스트를 가리킨다.

 

쓰레드의 구현

쓰레드는 운영체제에 따라 다양하게 구현할 수 있는데, 대부분 다음 세 가지 형태로 구현한다. 사용자 수준 쓰레드는 쓰레드 라이브러리를 이용하여 작동하는 형태이고, 커널 수준 쓰레드는 커널(운영체제)에서 지원하는 형태이다. 그리고 이 둘을 혼합한 형태가 혼합형 쓰레드이다.

 

  1. 사용자 수준 쓰레드 - 다대일 매핑
  2. 커널 수준 쓰레드 - 일대일 매핑
  3. 혼합형 쓰레드 - 다대다 매핑

 

<사용자 수준 쓰레드>

사용자 수준 쓰레드는 사용자 영역의 쓰레드 라이브러리로 구현하고, 쓰레드와 관련된 모든 행위를 사용자 영역에서 하므로 커널이 쓰레드의 존재를 알지 못한다. 여기서 쓰레드 라이브러리는 쓰레드의 생성과 종료, 쓰레드 간의 메시지 전달, 쓰레드의 스케줄링과 컨텍스트 등 정보를 보관한다. 

사용자 수준 쓰레드에서는 쓰레드 교환에 커널이 개입하지 않아 커널에서 사용자 영역으로 전환할 필요가 없다. 그리고 커널은 쓰레드가 아닌 프로세스를 한 단위로 인식하고 프로세서를 할당한다. 다수의 사용자 수준 쓰레드가 커널 수준 쓰레드 한 개에 매핑되므로 다대일 쓰레드 매핑이라고 한다. 

 

 

사용자 수준 쓰레드의 장점

  • 이식성이 높음 : 커널에 독립적으로 스케쥴링을 할 수 있어 모든 운영체제에 적용할 수 있다.
  • 오버헤드가 적음 : 스케쥴링이나 동기화를 하려고 커널을 호출하지 않으므로 커널 영역으로 전환하는 오버헤드가 줄어든다.
  • 유연한 스케쥴링이 가능 : 커널이 아닌 쓰레드 라이브러리에서 쓰레드 스케줄링을 제어하므로 응용 프로그램에 맞게 스케줄링할 수 있다.

사용자 수준 쓰레드의 단점

  • 시스템의 동시성을 지원하지 않음 : 쓰레드가 아닌 프로세스 단위로 프로세서를 할당하여 다중 처리 환경을 갖춰도 쓰레드 단위로 다중 처리를 하지 못한다. 동일한 프로세스의 쓰레드 한개가 대기 상태가 되면 이 중 어떤 쓰레드도 실행하지 못한다.
  • 확장에 제약이 따름 : 커널이 한 프로세스에 속한 여러 쓰레드에 프로세서를 동시에 할당할 수 없어 다중 처리 시스템에서 규모를 확장하기가 어렵다.
  • 쓰레드 간 보호 불가능 : 쓰레드 간 보호에 커널의 보호 방법을 사용할 수 없다. 쓰레드 라이브러리에서 쓰레드 간 보호를 제공해야 프로세스 수준에서 보호가 가능하다.

 

<커널 수준 쓰레드>

커널 수준 쓰레드는 사용자 수준 쓰레드의 한계를 극복하는 방법으로, 커널이 쓰레드와 관련된 모든 작업을 관리한다. 한 프로세스에서 다수의 쓰레드가 프로세서를 할당받아 병행으로 수행하고, 쓰레드 한 개가 대기 상태가 되면 동일한 프로세스에 속한 다른 쓰레드로 교환이 가능하다. 이때도 커널이 개입하므로 사용자 영역에서 커널 영역으로 전환이 필요하다. 커널 수준 쓰레드는 사용자 수준 쓰레드와 커널 수준 쓰레드가 일대일로 매핑된다. 따라서 사용자 수준 쓰레드를 생성하면 이에 대응하는 커널 쓰레드를 자동으로 생성한다.

 

커널 수준 쓰레드는 커널이 직접 스케줄링하고 실행하기에 사용자 수준 쓰레드의 커널 지원이 부족한 문제를 해결할 수 있지만, 커널이 전체 프로세스와 쓰레드 정보를 유지하여 오버헤드가 커진다. 대신 커널이 각 쓰레드를 개별적으로 관리할 수 있어 동일한 프로세스의 쓰레드들을 병행으로 수행할 수 있다. 동일한 프로세스에 있는 쓰레드 중 한 개가 대기 상태가 되더라도 다른 쓰레드를 실행할 수 있다는 장점이 있다. 하지만 이 과정에서도 커널 영역으로 전환하는 오버헤드가 발생하고 스케쥴링과 동기화를 하려면 더 많은 자원이 필요하다.

 

<혼합형 쓰레드>

혼합형 쓰레드는 사용자 수준 쓰레드와 커널 수준 쓰레드를 혼합한 구조이다. 이는 시스템 호출을 할 때 다른 쓰레드를 중단하는 다대일 매핑의 사용자 수준 쓰레드와 쓰레드 수를 제한하는 일대일 매핑의 커널 수준 쓰레드 문제를 극복하는 방법이다. 즉, 사용자 수준 쓰레드는 커널 수준 쓰레드와 비슷한 경량 프로세스에 다대다로 매핑되고, 경량 프로세스는 커널 수준 쓰레드와 일대일로 매핑된다. 결국 다수의 사용자 수준 쓰레드에 다수의 커널 쓰레드가 다대다로 매핑된다. 

 

 

프로세스 하나에는 경량 프로세스가 하나 이상 있고, 경량 프로세스에는 이에 대응하는 커널 쓰레드가 한 개 있다. 그리고 자원과 입출력 대기를 하려고 경량 프로세스 단위로 대기하므로 프로세스는 입출력을 완료할 때까지 대기할 필요가 없다.(다른 경량 프로세스는 대기상태가 아니기 때문) 어떤 경량 프로세스가 입출력 완료를 기다리더라도 동일한 프로세스에서 다른 경량 프로세스를 실행할 수 있기 때문이다.

 

[쓰레드 풀링]

시스템이 관리하는 쓰레드의 풀을 응용 프로그램에 제공하여 스레드를 효율적으로 사용할 수 있게 하는 방법이다. 즉, 미리 생성한 스레드를 재사용하도록 하여 스레드를 생성하는 시간을 줄여 시스템의 부담을 덜어준다. 또 동시에 생성할 수 있는 스레드수를 제한하여 시스템의 자원 소비를 줄여서 응용 프로그램의 전체 성능을 일정 수준으로 유지한다.



출처: https://coding-start.tistory.com/199 [코딩스타트]

 

프로세스와 스레드의 개념과 차이를 이해할 수 있다.
Goal
프로세스와 스레드의 개념을 설명할 수 있다.
프로세스와 스레드의 차이(Process vs Thread)를 이해할 수 있다.
멀티 프로세스 대신 멀티 스레드를 사용하는 이유를 알아본다.
프로세스와 스레드의 차이(Process vs Thread)
프로그램(Program) 이란
사전적 의미
“어떤 작업을 위해 실행할 수 있는 파일”
프로세스(Process) 란
사전적 의미
“컴퓨터에서 연속적으로 실행되고 있는 컴퓨터 프로그램”
메모리에 올라와 실행되고 있는 프로그램의 인스턴스(독립적인 개체)
운영체제로부터 시스템 자원을 할당받는 작업의 단위
즉, 동적인 개념으로는 실행된 프로그램을 의미한다.
참고 할당받는 시스템 자원의 예
CPU 시간
운영되기 위해 필요한 주소 공간
Code, Data, Stack, Heap의 구조로 되어 있는 독립된 메모리 영역
특징

프로세스는 각각 독립된 메모리 영역(Code, Data, Stack, Heap의 구조)을 할당받는다.
기본적으로 프로세스당 최소 1개의 스레드(메인 스레드)를 가지고 있다.

 
각 프로세스는 별도의 주소 공간에서 실행되며, 한 프로세스는 다른 프로세스의 변수나 자료구조에 접근할 수 없다.
한 프로세스가 다른 프로세스의 자원에 접근하려면 프로세스 간의 통신(IPC, inter-process communication)을 사용해야 한다.
Ex. 파이프, 파일, 소켓 등을 이용한 통신 방법 이용
스레드(Thread) 란
사전적 의미
“프로세스 내에서 실행되는 여러 흐름의 단위”
프로세스의 특정한 수행 경로
프로세스가 할당받은 자원을 이용하는 실행의 단위
특징

스레드는 프로세스 내에서 각각 Stack만 따로 할당받고 Code, Data, Heap 영역은 공유한다.
스레드는 한 프로세스 내에서 동작되는 여러 실행의 흐름으로, 프로세스 내의 주소 공간이나 자원들(힙 공간 등)을 같은 프로세스 내에 스레드끼리 공유하면서 실행된다.
같은 프로세스 안에 있는 여러 스레드들은 같은 힙 공간을 공유한다. 반면에 프로세스는 다른 프로세스의 메모리에 직접 접근할 수 없다.
각각의 스레드는 별도의 레지스터와 스택을 갖고 있지만, 힙 메모리는 서로 읽고 쓸 수 있다.
한 스레드가 프로세스 자원을 변경하면, 다른 이웃 스레드(sibling thread)도 그 변경 결과를 즉시 볼 수 있다.
자바 스레드(Java Thread) 란
일반 스레드와 거의 차이가 없으며, JVM가 운영체제의 역할을 한다.
자바에는 프로세스가 존재하지 않고 스레드만 존재하며, 자바 스레드는 JVM에 의해 스케줄되는 실행 단위 코드 블록이다.
자바에서 스레드 스케줄링은 전적으로 JVM에 의해 이루어진다.
아래와 같은 스레드와 관련된 많은 정보들도 JVM이 관리한다.
스레드가 몇 개 존재하는지
스레드로 실행되는 프로그램 코드의 메모리 위치는 어디인지
스레드의 상태는 무엇인지
스레드 우선순위는 얼마인지
즉, 개발자는 자바 스레드로 작동할 스레드 코드를 작성하고, 스레드 코드가 생명을 가지고 실행을 시작하도록 JVM에 요청하는 일 뿐이다.
멀티 프로세스와 멀티 스레드의 차이
멀티 프로세스
멀티 프로세싱이란
하나의 응용프로그램을 여러 개의 프로세스로 구성하여 각 프로세스가 하나의 작업(태스크)을 처리하도록 하는 것이다.
장점
여러 개의 자식 프로세스 중 하나에 문제가 발생하면 그 자식 프로세스만 죽는 것 이상으로 다른 영향이 확산되지 않는다.
단점
Context Switching에서의 오버헤드
Context Switching 과정에서 캐쉬 메모리 초기화 등 무거운 작업이 진행되고 많은 시간이 소모되는 등의 오버헤드가 발생하게 된다.
프로세스는 각각의 독립된 메모리 영역을 할당받았기 때문에 프로세스 사이에서 공유하는 메모리가 없어, Context Switching가 발생하면 캐쉬에 있는 모든 데이터를 모두 리셋하고 다시 캐쉬 정보를 불러와야 한다.
프로세스 사이의 어렵고 복잡한 통신 기법(IPC)
프로세스는 각각의 독립된 메모리 영역을 할당받았기 때문에 하나의 프로그램에 속하는 프로세스들 사이의 변수를 공유할 수 없다.
참고 Context Switching란?
CPU에서 여러 프로세스를 돌아가면서 작업을 처리하는 데 이 과정을 Context Switching라 한다.
구체적으로, 동작 중인 프로세스가 대기를 하면서 해당 프로세스의 상태(Context)를 보관하고, 대기하고 있던 다음 순서의 프로세스가 동작하면서 이전에 보관했던 프로세스의 상태를 복구하는 작업을 말한다.
멀티 스레드
멀티 스레딩이란
하나의 응용프로그램을 여러 개의 스레드로 구성하고 각 스레드로 하여금 하나의 작업을 처리하도록 하는 것이다.
윈도우, 리눅스 등 많은 운영체제들이 멀티 프로세싱을 지원하고 있지만 멀티 스레딩을 기본으로 하고 있다.
웹 서버는 대표적인 멀티 스레드 응용 프로그램이다.
장점
시스템 자원 소모 감소 (자원의 효율성 증대)
프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어 자원을 효율적으로 관리할 수 있다.
시스템 처리량 증가 (처리 비용 감소)
스레드 간 데이터를 주고 받는 것이 간단해지고 시스템 자원 소모가 줄어들게 된다.
스레드 사이의 작업량이 작아 Context Switching이 빠르다.
간단한 통신 방법으로 인한 프로그램 응답 시간 단축
스레드는 프로세스 내의 Stack 영역을 제외한 모든 메모리를 공유하기 때문에 통신의 부담이 적다.
단점
주의 깊은 설계가 필요하다.
디버깅이 까다롭다.
단일 프로세스 시스템의 경우 효과를 기대하기 어렵다.
다른 프로세스에서 스레드를 제어할 수 없다. (즉, 프로세스 밖에서 스레드 각각을 제어할 수 없다.)
멀티 스레드의 경우 자원 공유의 문제가 발생한다. (동기화 문제)
하나의 스레드에 문제가 발생하면 전체 프로세스가 영향을 받는다.
멀티 프로세스 대신 멀티 스레드를 사용하는 이유?
멀티 프로세스 대신 멀티 스레드를 사용하는 것의 의미?
쉽게 설명하면, 프로그램을 여러 개 키는 것보다 하나의 프로그램 안에서 여러 작업을 해결하는 것이다.
여러 프로세스(멀티 프로세스)로 할 수 있는 작업들을 하나의 프로세스에서 여러 스레드로 나눠가면서 하는 이유?
자원의 효율성 증대
멀티 프로세스로 실행되는 작업을 멀티 스레드로 실행할 경우, 프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어 자원을 효율적으로 관리할 수 있다.
–> 프로세스 간의 Context Switching시 단순히 CPU 레지스터 교체 뿐만 아니라 RAM과 CPU 사이의 캐쉬 메모리에 대한 데이터까지 초기화되므로 오버헤드가 크기 때문
스레드는 프로세스 내의 메모리를 공유하기 때문에 독립적인 프로세스와 달리 스레드 간 데이터를 주고 받는 것이 간단해지고 시스템 자원 소모가 줄어들게 된다.
처리 비용 감소 및 응답 시간 단축
또한 프로세스 간의 통신(IPC)보다 스레드 간의 통신의 비용이 적으므로 작업들 간의 통신의 부담이 줄어든다.
–> 스레드는 Stack 영역을 제외한 모든 메모리를 공유하기 때문
프로세스 간의 전환 속도보다 스레드 간의 전환 속도가 빠르다.
–> Context Switching시 스레드는 Stack 영역만 처리하기 때문
주의할 점!
동기화 문제
스레드 간의 자원 공유는 전역 변수(데이터 세그먼트)를 이용하므로 함께 상용할 때 충돌이 발생할 수 있다.
References
https://brunch.co.kr/@kd4/3
https://magi82.github.io/process-thread/
https://jaybdev.net/2017/06/05/Java-3/
http://includestdio.tistory.com/6
https://lalwr.blogspot.com/2016/02/process-thread.html
http://you9010.tistory.com/136
https://gmlwjd9405.github.io/2018/09/14/process-vs-thread.html

 

쓰레드(Thread)란 무엇인가?

2018-09-07

goodGid

 OS


쓰레드(Thread)란 무엇인가?

  • 쓰레드란 프로그램(프로세스) 실행의 단위이며
    하나의 프로세스는 여러개의 쓰레드로 구성이 가능하다.
  • 하나의 프로세스를 구성하는 쓰레드들은 프로세스에 할당된 메모리, 자원 등을 공유한다.
  • 프로세스와 같이 실행, 준비, 대기 등의 실행 상태를 가지며
    실행 상태가 변할때마다 쓰레드 문맥교환(context switching)을 수행한다.
  • 각 쓰레드별로 자신만의 스택 레지스터를 가진다.

  • 한순간에 하나의 쓰레드만이 실행 가능하다.

프로세스와 쓰레드의 차이

프로세스는 운영체제로부터 자원을 할당받는 작업의 단위이고
쓰레드는 프로세스가 할당받은 자원을 이용하는 실행의 단위이다.

  • 프로세스는 실행 중인 프로그램으로
    디스크로부터 메모리에 적재되어 CPU의 할당을 받을 수 있는 것을 말한다.
  • 하지만 프로세스 생성은 많은 시간과 자원을 소비한다.

 

  • 쓰레드는 프로세스 실행 단위라고 할 수 있다.
  • 한 프로세스 내에서 동작되는 여러 실행 흐름으로
    프로세스 내의 주소 공간이나 자원을 공유할 수 있다.
  • 이 경우 각각의 쓰레드는 독립적인 작업을 수행해야 하기 때문에 각자의 스택 PC 레지스터 값을 갖고 있다.

스택을 쓰레드마다 독립적으로 할당하는 이유

  • 스택은 함수 호출 시 전달되는 인자, 되돌아갈 주소값 및 함수 내에서 선언하는 변수 등을
    저장하기 위해 사용되는 메모리 공간이므로
    스택 메모리 공간 독립적이라는 것은
    독립적인 함수 호출이 가능하다는 것이고
    이는 독립적인 실행 흐름이 가능하게 한다.
  • 따라서 독립적인 실행 흐름을 위한 최소 조건으로 독립된 스택을 할당한다.

PC Resister를 쓰레드마다 독립적으로 할당하는 이유

  • PC 값은 쓰레드가 명령어의 어디까지 수행하였는지를 나타나게 된다.
  • 쓰레드는 CPU를 할당받았다가 스케줄러에 의해 다시 선점당한다.
    그렇기 때문에 명령어가 연속적으로 수행되지 못하고
    어느 부분까지 수행했는지 기억할 필요가 있다.
  • 따라서 PC 레지스터를 독립적으로 할당한다.

쓰레드(Thread)의 장점

  • 쓰레드는 프로세스보다 생성 및 종료시간, 쓰레드간 전환시간이 짧다.
  • 쓰레드는 프로세스의 메모리, 자원등을 공유하므로 커널의 도움없이 상호간에 통신이 가능하다.

쓰레드 동기화 방법의 종류

  • Mutex / Semaphore / Monitor
    공통점은 세가지 모두 운영체제의 동기화 기법이라는 것이다.
  • 뮤텍스(Mutual Exclusion)
    • 쓰레드의 동시 접근을 허용하지 않는다는 의미.
    • 뮤텍스의 쓰레드 동기화 방법은 임계영역에 들어가기 위해 이 뮤텍스를 가지고 있어야 들어갈 수 있다.
      예) 일종의 자물쇠와 같은 역할을 한다.
      임계영역에 들어간 쓰레드가 뮤텍스를 이용해 임계영역에서 본인이 나올때까지 다른 쓰레드가 못들어오게 내부에서 자물쇠로 잠근다.
  • 세마포어(Semaphore)
    • 세마포어 역시 뮤텍스와 비슷한 역할을 하지만
      세마포어는 동시 접근 동기화가 아닌 접근 순서 동기화에 더 관련있다.
  • 모니터(Monitor)
    • Mutex(Lock)와 Condition Variables(Queue라고도 함)을 가지고 있는 Synchronization 메카니즘이다.

 

  • 우선 뮤텍스 / 모니터 / 세마포어는 개념적으로 차이가 있다.
  • 전자(뮤텍스,모니터)는 상호 배제를 함으로써 임계구역에 하나의 쓰레드만 들어갈 수 있다.
  • 후자(세마포어)는 하나의 쓰레드(binary semaphore)만 들어가거나
    혹은 여러 개의 쓰레드(counting semaphore)가 들어가게 할 수도 있다.

 

Q. 뮤텍스와 모니터의 차이는?

  • 가장 큰 차이는 뮤텍스 다른 프로세스(애플리케이션)간에 동기화를 위해 사용한다.
  • 반면 모니터는 하나의 프로세스(애플리케이션)내에 다른 쓰레드 간에 동기화할 때 사용한다.
  • 또한, 뮤텍스는 보통 운영체제 커널 의해서 제공되는 반면에
    모니터는 프레임워크나 라이브러리 그 자체에서 제공된다.
  • 따라서 뮤텍스는 무겁고(heavy-weight) 느리며(slower)
    모니터는 가볍고(light-weight) 빠르다(faster).

Q. 세마포어와 모니터의 차이는?

  • Java에서는 모니터를 모든 객체에게 기본적으로 제공하고 있는 반면 C에서는 모니터를 사용할 수 없다.
  • 세마포어는 카운터라는 변수값으로 프로그래머가 상호 배제 정렬의 목적으로 사용 시
    매번 값을 따로 지정해줘야하는 등 조금 번거롭다.
  • 반면, 모니터는 이러한 일들이 캡슐화 되어 있어서(encapsulation)
    개발자는 카운터값을 1 또는 0으로 주어야 하는 고민을 할 필요 없이
    synchronized, wait(), notify() 등의 키워드를 이용해 좀 더 편하게 동기화할 수 있다.

Q. 뮤텍스와 세마포의 차이는?

  • 세마포어는 뮤텍스가 될 수 있지만
    뮤텍스는 세마포어가 될 수 없다.
  • 예를 들어 Casting을 한다고 보면
    (뮤텍스)세마포어 –> 가능
    (세마포어)뮤텍스 –> 불가능
  • 세마포어는 소유할 수 없는 반면
    뮤텍스는 소유할 수 있고 소유자가 이에 책임을 진다.
  • 뮤텍스는 1개만 동기화가 되지만
    세마포어는 하나 이상을 동기화 할 수 있다.

변기가 하나뿐인 화장실에서는 앞의 사람이 볼일을 마치고 나가야 다음 사람이 들어갈 수 있다. 이렇게 한번에 오직 하나만 처리할 수 있는 대상에 사용하는 것이 뮤텍스이다. 변기가 세개인 화장실에서는 동시에 세 사람이 볼일을 볼 수 있고 이 세 사람 중 아무나 한명이 나오면 다음 사람이 볼일을 볼 수 있다. 이렇게 동시에 제한된 수의 여러 처리가 가능하면 세마포어이다. 만약 변기 세개짜리 화장실의 각 변기에 대해 뮤텍스를 사용한다면 대기중인 사람은 각 변기 앞에 줄을 서는 것이고 이렇게 되면 옆 칸이 비어도 들어가지 못하게 된다. 만약 변기 세개를 묶어서 뮤텍스를 사용한다면 변기 수에 관계없이 무조건 한명만 사용할 수 있게 된다. 이 예에서 변기는 동기화 대상, 사람은 그 동기화 대상에 접근하는 쓰레드를 나타낸다. 뮤텍스와 세마포어의 목적은 특정 동기화 대상이 이미 특정 쓰레드에 의해 사용중일 경우 다른 쓰레드가 해당 동기화 대상에 접근하는 것을 제한하는 것으로 동일하지만 관리하는 동기화 대상이 몇개 인가에 따라 차이가 생기게 되는 것이다.

 

 

http://tcpschool.com/java/java_thread_concept

 

스레드의 개념


프로세스(process)란?

프로세스(process)란 단순히 실행 중인 프로그램(program)이라고 할 수 있습니다.

즉, 사용자가 작성한 프로그램이 운영체제에 의해 메모리 공간을 할당받아 실행 중인 것을 말합니다.

이러한 프로세스는 프로그램에 사용되는 데이터와 메모리 등의 자원 그리고 스레드로 구성됩니다.


스레드(thread)란?

스레드(thread)란 프로세스(process) 내에서 실제로 작업을 수행하는 주체를 의미합니다.

모든 프로세스에는 한 개 이상의 스레드가 존재하여 작업을 수행합니다.

또한, 두 개 이상의 스레드를 가지는 프로세스를 멀티스레드 프로세스(multi-threaded process)라고 합니다.


스레드의 생성과 실행

자바에서 스레드를 생성하는 방법에는 다음과 같이 두 가지 방법이 있습니다.

 

1. Runnable 인터페이스를 구현하는 방법

2. Thread 클래스를 상속받는 방법

 

두 방법 모두 스레드를 통해 작업하고 싶은 내용을 run() 메소드에 작성하면 됩니다.

 

다음 예제는 위의 두 가지 방법을 사용하여 스레드를 생성하고 실행하는 예제입니다.

예제

class ThreadWithClass extends Thread {

    public void run() {

        for (int i = 0; i < 5; i++) {

            System.out.println(getName()); // 현재 실행 중인 스레드의 이름을 반환함.

            try {

                Thread.sleep(10);          // 0.01초간 스레드를 멈춤.

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    }

}

 

class ThreadWithRunnable implements Runnable {

    public void run() {

        for (int i = 0; i < 5; i++) {

            System.out.println(Thread.currentThread().getName()); // 현재 실행 중인 스레드의 이름을 반환함.

            try {

                Thread.sleep(10);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    }

}

 

public class Thread01 {

    public static void main(String[] args){

        ThreadWithClass thread1 = new ThreadWithClass();       // Thread 클래스를 상속받는 방법

        Thread thread2 = new Thread(new ThreadWithRunnable()); // Runnable 인터페이스를 구현하는 방법

 

        thread1.start(); // 스레드의 실행

        thread2.start(); // 스레드의 실행

    }

}

코딩연습 ▶

실행 결과

Thread-0

Thread-1

Thread-0

Thread-1

Thread-0

Thread-1

Thread-0

Thread-1

Thread-0

Thread-1

 

위 예제의 실행 결과를 살펴보면, 생성된 스레드가 서로 번갈아가며 실행되고 있는 것을 확인할 수 있습니다.

 

Thread 클래스를 상속받으면 다른 클래스를 상속받을 수 없으므로, 일반적으로 Runnable 인터페이스를 구현하는 방법으로 스레드를 생성합니다.

 

Runnable 인터페이스는 몸체가 없는 메소드인 run() 메소드 단 하나만을 가지는 간단한 인터페이스입니다.


스레드의 우선순위

자바에서 각 스레드는 우선순위(priority)에 관한 자신만의 필드를 가지고 있습니다.

이러한 우선순위에 따라 특정 스레드가 더 많은 시간 동안 작업을 할 수 있도록 설정할 수 있습니다.

필드설명

static int MAX_PRIORITY 스레드가 가질 수 있는 최대 우선순위를 명시함.
static int MIN_PRIORITY 스레드가 가질 수 있는 최소 우선순위를 명시함.
static int NORM_PRIORITY 스레드가 생성될 때 가지는 기본 우선순위를 명시함.

 

getPriority()와 setPriority() 메소드를 통해 스레드의 우선순위를 반환하거나 변경할 수 있습니다.

스레드의 우선순위가 가질 수 있는 범위는 1부터 10까지이며, 숫자가 높을수록 우선순위 또한 높아집니다.

 

하지만 스레드의 우선순위는 비례적인 절댓값이 아닌 어디까지나 상대적인 값일 뿐입니다.

우선순위가 10인 스레드가 우선순위가 1인 스레드보다 10배 더 빨리 수행되는 것이 아닙니다.

단지 우선순위가 10인 스레드는 우선순위가 1인 스레드보다 좀 더 많이 실행 큐에 포함되어, 좀 더 많은 작업 시간을 할당받을 뿐입니다.

 

그리고 스레드의 우선순위는 해당 스레드를 생성한 스레드의 우선순위를 상속받게 됩니다.

 

예제

class ThreadWithRunnable implements Runnable {

    public void run() {

        for (int i = 0; i < 5; i++) {

            System.out.println(Thread.currentThread().getName()); // 현재 실행 중인 스레드의 이름을 반환함.

            try {

                Thread.sleep(10);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    }

}

 

public class Thread02 {

    public static void main(String[] args){

        Thread thread1 = new Thread(new ThreadWithRunnable());

        Thread thread2 = new Thread(new ThreadWithRunnable());

 

      thread2.setPriority(10); // Thread-1의 우선순위를 10으로 변경함.

 

      thread1.start(); // Thread-0 실행

      thread2.start(); // Thread-1 실행

 

        System.out.println(thread1.getPriority());

        System.out.println(thread2.getPriority());

    }

}

코딩연습 ▶

실행 결과

5

10

Thread-1

Thread-0

Thread-1

Thread-0

Thread-1

Thread-0

Thread-1

Thread-0

Thread-1

Thread-0

 

main() 메소드를 실행하는 스레드의 우선순위는 언제나 5이므로, main() 메소드 내에서 생성된 스레드 Thread-0의 우선순위는 5로 설정되는 것을 확인할 수 있습니다.

 

위의 예제는 ②번 라인에서 Thread-0이 먼저 실행되고, ③번 라인에서 Thread-1이 나중에 실행됩니다.

따라서 만약 ①번 라인이 존재하지 않는다면, Thread-0이 먼저 실행되고, Thread-1이 나중에 실행될 것입니다.

하지만 ①번 라인에서 Thread-1의 우선순위를 10으로 변경했기 때문에, Thread-1이 나중에 실행됐더라도 우선순위가 Thread-0보다 높아 먼저 실행되는 것입니다.