스레드 스케줄러Thread.yield, 스레드 우선순위에 의존하지 말자. 견고성과 이식성을 모두 해치는 행위이다.
스레드 우선순위는 프로그램의 서비스 품질을 높이는데 드물게 쓰일 수는 있지만 프로그램을 고치는 용도로 사용해서는 안된다.

• 정확성이나 성능이 운영체제 고유의 스레드 스케줄러에 따라 달라지는 프로그램일수록 다른 플랫폼에 이식하기 어렵다.

• 견고하고 이식성 좋은 프로그램을 작성하기 위해서 고려해야 할 것들

    ◦  실행 가능한 스레드의 평균 개수를 프로세서 수 보다 지나치게 많아지지 않도록 관리할 것

    ◦  즉 실행가능한 스레드 수를 가능한 적게 유지하는 것이 중요하다.


실행 가능한 스레드 수를 적게 유지하는 방법

• 실행 준비가 된 스레드들은 맡은 작업을 완료할 때 까지 계속 실행되도록 할 것

    ◦  단 실행 가능한 스레드 수 와 전체 스레드 수는 구분해야 한다. (대기 중인 스레드 = 실행 불가)

• 스레드는 당장 처리해야 할 작업이 없다면 실행 되어서는 안된다.

• 스레드는 Busy Waiting 상태가 되면 안된다.

    ◦  Busy Waiting 상태

-  스레드 스케줄러 환경의 변화에 취약하다. (이식성이 낮다)

-  프로세서에 부담을 주어 다른 작업이 실행의 기회를 박탈당한다. (성능이 낮다)

-  Busy Waiting이 발생하는 코드 예시 (작가평 : 끔찍한 코드이다!)

public class SlowCountDownLatch {
  private int count;

  public SlowCountDownLatch(int count) {
    if (count < 0) throw new IllegalArgumentException(count + " < 0");
    this.count = count;
  }

  public void await() {
    while (true) {
      synchronized(this) { if (count == 0) return; }
    }
  }

  public synchronized void countDown() {
    if (count != 0) count--;
  }

}

Thread.yield 사용을 주의하라

• Thread.yield : 다른 스레드에게 실행을 양보하는 메서드

    ◦  실행 중인 스레드를 RUNNABLE (실행 대기) 상태로 바꾼다.

          -  스레드가 실행되었는데, 그 실행이 잠시동안 무의미한 경우가 있을 수 있다.

          -  이런 경우 스레드를 잠시 실행 대기 상태로 돌려놓으면 CPU의 자원의 소모를 방지할 수 있다.

          -  이 때 Thread.yield 메소드가 유용하게 사용될 수 있다.

• 특정 스레드가 다른 스레드에 비해 CPU 자원을 할당받지 못하는 경우에도 Thread.yield 사용은 지양하자

    ◦  증상이 호전될 수 있어도 여전히 이식성이 나쁘다

          -  JVM 종류에 따라 차이가 미미할수도, 악화될수도 있다.

• 차라리 어플리케이션 구조를 바꿔 동시에 실행 가능한 스레드 수를 줄이는 것이 좋다.


스레드 우선순위 조정에 주의하라

• 스레드 우선순위는 자바에서 이식성이 가장 나쁜 특성 중 하나이다.

    ◦  A 타입의 JVM 에서 1-2-3 의 순서로 실행되었다고 하더라도, B 타입의 JVM에서 동일한 순서로 실행되리라는 보장이 없다.

          -  A 타입에서 1-2-3 의 순서로 실행된 것이 B 타입의 JVM 에서는 3-1-2 의 순서로 실행될 수 있음

          -  즉 1-2-3 이 최적의 성능을 보장하는 우선순위 였다고 해도, 다른 JVM 에서 3-1-2 의 순서로 실행되어 버리면 다시 성능이 나빠진다.

• 특히 응답 불가 문제는 스레드 우선순위로 해결해선 안된다.

    ◦  진짜 원인을 찾아 수정하기 전까지 같은 문제가 반복해서 발생할 것이다.

 스레드 개념

• 프로세스 안에서 실행되는 여러 흐름 단위

    ◦  프로세스가 생성될 때, 기본적으로 하나의 스레드가 함께 생성된다.

    ◦  즉 프로세스마다 최소 한 개 이상의 스레드가 존재할 수 있다.


 멀티스레드

 하나의 프로세스에 두 개 이상의 스레드가 존재하는 구조로, 여러 작업을 동시에 처리할 수 있다.

 각 스레드마다 별도의 스택 영역이 독립적으로 주어지지만, 텍스트데이터 영역은 소속된 프로세스의 것을 공유하여 사용한다.

    ◦  프로세스는 자신만의 고유 공간과 자원을 할당받아 사용하는데 반해 스레드는 프로세스 내부의 다른 스레드와

         공간, 자원을 공유하면서 사용한다는 점에서 차이가 있다.

 

 사용자 스레드(User threads)

    ◦  사용자 수준(user level)에서 실행되며 thread library에 의해 관리된다.

    ◦  동일한 메모리 영역에서 스레드가 생성/관리 되므로 속도가 빠르다.

 

 커널 스레드(Kernel thread)

    ◦  커널 수준(kernel level)에서 실행되며 운영체제에 의해 직접 관리된다.


 다중 스레드 모델

 Many-to-One Model

    ◦  여러 사용자 스레드를 하나의 커널 스레드에 mapping 한 모델

    ◦  concurrency 는 얻을 수 있지만 parallelism 을 얻을 수 없다.

    ◦  여러 개의 사용자 스레드 중 하나가 시스템 호출 등으로 중단되면 나머지 모든 스레드 역시 중단된다.

    ◦  멀티코어 or 멀티프로세스의 이점을 충분히 활용할 수 없다.

 

 One-to-One Model

    ◦  하나의 사용자 스레드를 하나의 커널 스레드에 mapping 한 모델

    ◦  blocking 문제가 발생하지 않는다.

    ◦  멀티 코어나 멀티 프로세스의 이점을 활용할 수 있다.

    ◦  사용자 스레드를 만드는 것은 곧 커널 스레드를 만드는 것을 의미한다. 커널 스레드가 많아지면 성능상의 문제가 발생할 수 있다.

    ◦  가장 일반적으로 사용 되는 모델이다.

          -  대부분의 시스템에서 처리 CPU 수가 증가함에 따라 커널 스레드의 개수를 제한하는 것의 중요성이 줄어들었기 때문에
              Many-to-Many 모델보다 더 많이 사용된다.

 

 Many-to-Many Model

    ◦  많은 사용자 스레드를 같거나 더 적은 수의 커널 스레드에 mapping 한 모델

    ◦  blocking 문제가 발생하지 않는다.

    ◦  멀티 코어나 멀티 프로세스의 이점을 활용할 수 있다.

    ◦  가장 flexible 하지만 구현하기 어렵다.

 

 Two-Level Model

    ◦  Many-to-Many 방식과 One-to-One 방식이 함께 존재하는 모델

    ◦  두 모델의 장점을 모두 누리기 위해 고안된 모델이다.


 멀티스레드의 장단점

 장점

    ◦  응답성

          -  동시에 여러 작업을 수행할 수 있기 때문에 사용자에 대한 응답성을 증가시킨다.

    ◦  자원 공유

          -  프로세스는 공유 메모리와 메시지 전달을 통해서만 자원을 공유할 수 있지만 스레드는 동일한 프로세스 내부의 스레드들과

             자원을 공유하기 때문에 자원 손실이 적다.

          -  스레드 생성은 프로세스 생성보다 일반적으로 시간과 메모리를 적게 소비한다

          -  자원을 공유하기 때문에 Context switching 속도는 프로세스 보다 스레드 사이에서 더 빠르다.

• 단점

    ◦  안전성

          -  스레드 끼리 메모리 공간을 공유하기 때문에, 하나의 스레드가 메모리를 훼손하면 다른 스레드의 작업에도 문제가 생길 수 있다.

          -  Critical Section 과 동기화 기법

              -  하나의 스레드/프로세스가 수정 가능한 공유 자원을 액세스하고 있을 때,

                  그 스레드/프로세스에 의해 참조되는 영역을 Critical Section 이라고 한다.

              -  특정 데이터에 여러 스레드/프로세스가 동시 접근하는 경우 문제가 발생할 수 있기 때문에,
                  동기화 기법을 이용해 특정 데이터에는 한번에 하나의 스레드/프로세스만 접근하도록 제한해야 한다.


 멀티 프로세스

 멀티 프로세스

    ◦  여러개의 프로세스가 동시에 병렬적으로 처리되는 상황을 의미한다.

    ◦  보통 하나의 컴퓨터에 여러개의 CPU를 장착해야 가능하다. 1코어 CPU의 경우 한번에 하나의 프로세스만 처리할 수 있기 때문이다.

 

    ◦  장점 : 안전성

              -  메모리 침범 문제를 OS 차원에서 해결해준다

 

    ◦  단점 : 성능 저하

              -  프로세스는 독립된 메모리 영역을 가지기 때문에 작업량이 많을수록 메모리 효율이 떨어진다.

                  또한 Context Switching 으로 인한 오버헤드가 발생하기 쉽다.


참고자료

 

운영체제 - YES24

운영체제

www.yes24.com

 

'CS Knowledge > 운영체제' 카테고리의 다른 글

[OS] CPU 스케줄링 알고리즘  (0) 2022.09.16
[OS] CPU 스케줄링 개념  (0) 2022.09.16
[OS] 프로세스와 Context Switching  (0) 2022.09.08
[OS] 운영체제 구조  (0) 2022.09.07
[OS] 운영체제 개요  (0) 2022.09.07

 

운영체제란?

운영체제(operating system)란, 컴퓨터 하드웨어를 관리하는 소프트웨어이다.

운영체제는 컴퓨터 하드웨어를 관리할 뿐만 아니라, 컴퓨터 시스템의 자원들을 효율적으로 관리하고, 응용 프로그램과 하드웨어 간의 인터페이스로써 다른 응용 프로그램이 유용한 작업을 할 수 있는 환경을 제공해준다.

즉, 운영 체제는 사용자가 컴퓨터를 편리하고 효과적으로 사용할 수 있는 환경을 제공하는 시스템 소프트웨어라고 할 수 있다.

 

 

개발자는 운영체제를 왜 공부해야 할까? 기업에서는 왜 그렇게 운영체제 이론을 강조하면서 기술질문을 하는 것일까?

 

우선 내가 만든 프로그램, 혹은 내가 사용하는 프로그램이 컴퓨터에서 어떻게 수행되는지를 알아야 에러가 발생했을 때 빠르게 원인을 찾아
해결할 수 있고, 프로그램의 실행 속도나 메모리 성능을 지속적으로 개선하는 등 서비스를 확장해 나갈 수 있기 때문이다.

더불어 운영체제를 잘 이해하면 프로그램을 만들기 전에 개발 난이도, 비용, 성능 등을 예측할 수 있다.
이걸 사전에 파악하는 것은 한정된 시간과 비용으로 서비스를 개발해야 하는 기업 입장에서는 매우 중요할 것이다.

 

나 역시 처음 웹 개발 공부를 시작할 때에는 웹 개발에 운영체제 지식이 왜 필요해? 그건 임베디드 하는 애들한테나 중요한거 아니야?
라는 생각을 하곤 했지만... 웹 서비스를 배포하거나 서버 트래픽 관리, DB 쿼리 최적화 작업만 해도 수많은 프로세스 에러를 만나게 되면서
운영체제를 공부해야 한다고 주변에 외치고 다녔더랜다.

 

이러한 운영체제의 종류에는 Windows, Linux, UNIX, MS-DOS 등이 있으며 각각 장단점이 있으므로 사용하고자 하는 용도에 알맞게 선택하여 사용하는 것이 좋다.

 

 

프로세스 관리

운영체제의 역할 중 하나는 프로세스 관리 이며, 운영체제에서 작동하는 응용 프로그램을 관리하는 기능이다.

컴퓨터 CPU가 한번에 처리할 수 있는 양은 제한적이다. 따라서 여러 응용 프로그램이 동시에 CPU을 사용하려고 한다면 운영체제는 이를 적절히 배분해 줄 수 있어야 할 것이다. 즉 프로세스 관리는 프로세서(CPU)를 관리하는 것이라고 볼 수도 있다.

 

운영체제는 현재 CPU를 점유해야 할 프로세스를 결정하고, 실제로 CPU를 프로세스에 할당한 다음, 이 프로세스의 공유 자원 접근 및 통신 등을 관리한다. 이러한 작업을 우리는 스케줄링, 동기화IPC 통신 이라고 부르는 것이다.
(각각이 어떤 작업을 의미하는지는 이후 포스팅에서 알아보자)

 

 

프로세스와 스레드

프로세스란, 정 프로그램이 메모리 상에서 실행중인 작업 이다. 이 때 프로세스 안에서 실행되는 여러 흐름 단위를 스레드 라고 한다.

프로세스가 생성될 때, 기본적으로 하나의 스레드가 함께 생성된다. 프로세스마다 최소 1개 이상의 스레드가 존재할 수 있다.

 

하나의 프로세스에는 CodeDataHeap 이라는 세가지 메모리 영역이 존재한다.

 

Code : 코드 자체, 프로그램 명령 등이 저장되는 영역

• Data : 전역변수, 정적변수, 배열 등이 저장되는 영역

    -  초기화 된 데이터는 data 영역에 저장된다.

    -  초기화 되지 않은 데이터는 BSS(Block Started by Symbol) 영역에 저장된다.

• Heap : 동적 할당된 데이터(new, malloc 등)가 저장되는 영역

 

이 때 하나의 프로세스에 여러개의 스레드가 존재하는 경우, 각 스레드에는 별도의 Stack 영역이 독립적으로 주어지지만

Code, Data, Heap 영역은 소속된 프로세스의 것을 공유하여 사용한다.

 

• Stack : 지역변수, 매개변수, 리턴 값 등이 저장되는 영역 (임시 메모리 영역)

 

즉 프로세스는 자신만의 고유 공간과 자원을 할당받아 사용하는데 반해,

스레드는 프로세스 내부에서 다른 스레드와 공간, 자원을 공유하면서 사용한다는 점에서 공간/자원 사용 측면의 차이가 있다.

 

 

멀티 프로세스

멀티 프로세스란 여러개의 프로세스가 동시에 병렬적으로 처리되는 상황을 의미한다.

보통 하나의 컴퓨터에 여러개의 CPU를 장착해야 가능하다. 단일 코어 CPU는 한번에 하나의 프로세스만 처리할 수 있기 때문이다.

 

• 장점 : 안전성 (메모리 침범 문제를 OS 차원에서 해결해준다)

• 단점 : 프로세스가 각각 독립된 메모리 영역을 갖고 있기 때문에, 작업량이 많을수록 오버헤드가 발생할 수 있다.

              또한 Context Switching 으로 인한 성능 저하가 발생한다.

 

• Context Switching

    -  프로세스의 상태 정보를 저장하고 복원하는 일련의 과정

    -  프로세스는 동작 상태와 대기 상태를 반복한다. 동작 중인 프로세스가 대기 상태가 되면 해당 프로세스의 정보는 보관되어야 한다.
       이후 대기 상태에서 다시 동작 상태가 되면 보관중이던 정보는 다시 복원되어야 한다. 이 과정이 바로 Contect Switching 이다.

    -  프로세스는 각각 독립된 메모리 영역을 할당받아 사용하기 때문에, 캐시 메모리 초기화처럼 무거운 작업이 진행될 때 오버헤드가
       발생할 수 있다.

 

 

멀티 스레드

멀티 스레드하나의 프로세스에서 여러 스레드가 각각 별개의 작업을 하나씩 처리하는 것을 의미한다.

즉 멀티 스레드를 이용하면 하나의 프로세스만 가지고 여러 작업을 동시에 처리할 수 있다.

 

멀티 프로세스로 여러 작업을 동시에 처리하는 것 보다 하나의 프로세스에서 멀티 스레드로 여러 작업을 동시에 처리하면

메모리 공간과 시스템 자원 소모를 줄일 수 있다.

 

또한 하나의 프로세스에 속한 스레드들은 Code, Data, Heap 공간을 공유하기 때문에

별개의 Code, Data, Heap 공간을 사용하는 멀티 프로세스 방식 보다 통신 방법이 간단하고 속도 역시 빠르다.

 

• 장점 : 멀티 프로세스 방식 보다 시간, 자원 손실이 적으며 쓰레드끼리 전역 변수와 정적 변수를 공유할 수 있다.

• 단점 : 안전성의 문제가 발생할 수 있다. 메모리 공간을 공유하기 때문에, 하나의 스레드가 메모리를 훼손하면, 모든 스레드의 작동이
              불가능해진다. 이러한 문제는 Critical Section동기화 기법을 적용하여 방지할 수 있다.

 

• Critical Section

    -  특정 데이터에 둘 이상의 쓰레드가 동시에 접근해서 연산을 실행하는 경우 문제가 발생할 수 있다.
       이러한 문제를 일으키는 코드 블록을 Critical Section 이라고 한다. 즉 한 순간에 하나의 쓰레드만 접근해야 하는 공유 리소스 영역
       (전역 변수 등)에 접근하는 코드 블록을 Critical Section 이라고 한다.

    -  동기화 기법을 이용하면 임계 영역에는 한번에 단 하나의 쓰레드만 접근하도록 제한할 수 있다.

 

• 동기화 기법의 종류

    -  크리티컬 섹션(Critical Section) 기반 동기화 (유저 모드 동기화)

    -  인터락 함수(Interlocked Family Of Function) 기반 동기화 (유저 모드 동기화)

    -  뮤텍스(Mutex) 기반 동기화 (커널 모드 동기화)

    -  세마포어(Semaphore) 기반 동기화 (커널 모드 동기화)

    -  이름있는 뮤텍스(Named Mutex) 기반 프로세스 동기화 (커널 모드 동기화)

    -  이벤트(Event) 기반 동기화 (커널 모드 동기화)

 

동기화 기법마다 사용해야 하는 경우가 특별하게 정해져 있는 것은 아니지만,
목적에 적합한 동기화 기법을 잘 선택해서 사용하면 간결하고 정확한 코드를 작성할 수 있다.

 

 

참고자료

 

👨🏻‍💻 Tech Interview

최종 수정 : 6/9/2022, 1:38:54 PM

gyoogle.dev

 

[Linux] BSS란 무엇인가?

1. BSS란? BSS는 block started by symbol의 약어이다. .bss나 bss는 초기에 오직 제로 값으로 표시된 정적으로 할당된 변수가 포함된 데이터 세그먼트의 일부로 컴파일러나 링커에 의해  사용된다. 즉,

dreamlog.tistory.com

 

[13. 쓰레드 동기화 기법]

* 이 내용은 '뇌를 자극하는 윈도우즈 시스템 프로그래밍' 책의 내용을 정리한 것 입니다. 쓰레드 동기화란 무엇인가? 두 가지 관점에서의 쓰레드 동기화 여기서 말하는 동기화는, 순서에 있어서

popcorntree.tistory.com

 

운영체제 - YES24

운영체제

www.yes24.com

 

'CS Knowledge > 운영체제' 카테고리의 다른 글

[OS] CPU 스케줄링 개념  (0) 2022.09.16
[OS] 스레드와 멀티스레드  (0) 2022.09.08
[OS] 프로세스와 Context Switching  (0) 2022.09.08
[OS] 운영체제 구조  (0) 2022.09.07
[OS] 운영체제 개요  (0) 2022.09.07