[OS]Ch4. Thread and Concurrency

sookyung kang·2022년 10월 19일
0

운영체제(공룡책)

목록 보기
3/5

1. What is Thread?

  • 스레드(Thread)는 CPU 수행의 기본 단위 또는 프로세스 안의 제어권의 흐름이다.

  • 스레드가 수행되는 환경을 Task라고 부르는데, 전통적인 프로세스는 하나의 스레드가 있는 Task와 일치한다.

  • 한 프로세스가 하나의 스레드를 이용하여 한 번에 한 작업만 수행하는 것은 싱글 스레드(Single thread), 한 프로세스가 여러 스레드로 동시에 여러 작업을 수행하는 것은 멀티 스레드(Multi thread)라고 한다.

  • 멀티 스레드는 코드와 adress space, operating resource 를 공유한다.

  • 프로세스 내의 스레드는 모두 각각 독립적인 실행 파일이며, 모든 스레드는 프로세스의 일부이다. 프로세스를 여러 개 수행해도 되지만 굳이 스레드를 사용하는 이유는 다음과 같다.

  1. 프로세스를 생성하거나 Context switching 하는 작업은 너무 무겁고 잦으면 성능 저하가 발생하는데, 스레드를 생성하거나 switching 하는 것은 그에 비해 가볍다.

  2. 두 프로세스가 하나의 데이터를 공유하려면 메시지 패싱이나 공유 메모리 또는 파이프를 사용해야 하는데, 이는 효율도 떨어지고 개발자가 구현, 관리하기도 번거롭다.

2. Multithreading

Single and Multithreaded Processes

->어떻게 다른지

Multiple cores

  • 프로세서가 여러 개인 경우 멀티 스레드를 통해 병렬성(Parallelism)을 높일 수 있다. 즉, 여러 작업이 동시에 수행될 수 있다.
    이는 프로세스의 스레드들이 각각 다른 프로세서에서 병렬적으로 수행될 수 있기 때문이다. 병렬성은 CPU의 개수에 비례한다.

Single core

  • 프로세서가 하나인 경우엔 멀티 스레드를 통해 동시성(Concurrency)을 높일 수 있다. 실제로는 각각의 시간에 한 작업만 수행되지만(illusion of parallelism), 병렬적으로 수행되는 것처럼 보이는 것이다. 만약 한 스레드가 blocked(waiting) 되더라도 커널이 다른 스레드로 switch 시켜 실행할 수 있어서, 하나의 프로세서임에도 불구하고 빠른 처리가 가능하고 계산 속도가 증가한다.
    Provide computation speed-up even on a single processor system because if an I/O bound thread blocks, the kernel can switch to another thread of the same process.

Multithreading 장점

  1. 응답성(Responsiveness)
    싱글 스레드인 경우, 작업이 끝나기 전까지 사용자에게 응답하지 않는다. 반면 멀티스레드인 경우 작업을 분리해서 수행하므로 실시간으로 사용자에게 응답할 수 있다.

  2. 자원 공유(Resource sharing)
    프로세스는 오직 공유 메모리나 메시지 패싱을 이용해서 자원을 공유할 수 있지만, 스레드는 자신이 속한 프로세스 내의 스레드들과 메모리나 자원을 공유하여 효율적으로 사용할 수 있다.

  3. 경제성(Economy)
    프로세스를 새로 생성하는 비용보다 스레드를 새로 생성하는 게 훨씬 싸다. 그리고 Context switching의 오버헤드 또한 스레드가 더 경제적이다. 실제로 Solaris에서 프로세스 생성은 스레드 생성보다 30배 느리고, switching은 5배 느리다.

  4. 확장성(Scalability)
    싱글 스레드인 경우 한 프로세스는 오직 한 프로세서에서만 수행 가능하다. 반면 멀티 스레드인 경우 한 프로세스를 여러 프로세서에서 수행할 수 있으므로 훨씬 효율적이다.
    (Achieve concurrency and parallelism, Throughput (overlap computation and I/O), Utilization of MP Architectures)

3. User-level Thread vs Kernel-level Thread

  • 유저 스레드(User-level Thread)는 커널 위에서 커널의 지원 없이 유저 수준의 스레드 라이브러리(Thread Library)가 관리하는 스레드다.

  • 반면 커널 스레드(Kernel-level Thread)는 커널이 지원하는 스레드다.
    이 커널을 multithreaded kernel 이라고 한다.
    - Most contemporary operating systems (e.g., Windows XP, Linux, Solaris, Mac OS X, etc.) are multithreaded kernels.

  • 커널 스레드를 사용하면 안정적이지만 유저 모드에서 커널 모드로 계속 바꿔줘야 하기 때문에 성능이 저하된다. 반대로 유저 스레드를 사용하면 안정성은 떨어지지만 성능이 저하되지는 않는다

  • user-level thread와 kernel-level thread 사이의 mapping

    • non-multithreaded kernels 에서 user-level thread는 regular process와 같이 실행된다.
    • multithreaded kernels 에서 user와 kernel thread 사이에 관계가 반드시 존재한다.

  1. Many-to-One Model
    하나의 커널 스레드에 여러 유저 스레드를 연결하는 모델이다. 유저 공간의 스레드 라이브러리를 통해서 스레드가 관리되므로 효율적이다. 라이브러리를 위한 모든 코드나 자료구조가 유저 공간에 존재하므로 라이브러리의 함수 호출이 시스템 콜이 아니라 지역 함수 호출의 결과를 낳기 때문이다.
    반면, 한번에 한 유저 스레드만 커널에 접근할 수 있기 때문에 멀티 프로세서 시스템에서 병렬적인 수행을 할 수 없어 요즘에는 잘 사용되지 않는 방식이다. 한 유저 스레드의 시스템 콜로 인해 block 되면 프로세스 전체가 block 되기 때문이다.

  2. One-to-One Model
    하나의 커널 스레드에 하나의 유저 스레드가 대응하는 모델이다. 동시성(Concurrency)을 높여주고, 멀티 프로세서 시스템에서 동시에 여러 스레드를 수행할 수 있도록 해준다.
    단점으로는, 유저 스레드를 늘리면 커널 스레드도 똑같이 늘어나는데, 커널 스레드의 생성은 오버헤드가 크기 때문에 성능 저하가 발생할 수 있다.

  3. Many-to-Many Model
    여러 유저 스레드에 더 적거나 같은 수의 커널 스레드가 대응하는 모델이다. 운영체제는 충분한 수의 커널 스레드를 만들 수 있으며, 커널 스레드의 구체적인 개수는 프로그램이나 작동 기기에 따라 다르다. 멀티 프로세서 시스템에서는 싱글 프로세서 시스템보다 더 많은 커널 스레드가 만들어진다.
    완전한 동시성은 아니지만, Many-to-one Model에 비해 더 높은 동시성을 갖는다. 그리고 One-to-One Model의 단점이었던 커널 스레드 생성의 오버헤드도 걱정할 필요 없다.

  4. Two-level Model
    Many-to-Many Model에서 확장된 개념이다. 특정 유저 스레드를 위한 커널 스레드를 별도로 제공하는 모델이다. 점유율이 높아야 하는 유저 스레드를 더 빠르게 처리할 수 있다.

Thread Mapping and Scheduling

  • Parallel Execution due to
    - Concurrency of threads on Virtual Processors
    - Concurrency of threads on Physical Cores
  • True Parallelism
    - Single Thread : Single Core = 1:1

Thread Libraries

  • Thread Libraries는 programmer가 API로 스레드를 managing하도록 제공한다
  1. User-level thread library
  • Provides a library entirely in user space with no kernel support (i.e., no mapping).
  • All code and data structures for the library exist in user space.
  • Usually used in a non-multithreaded kernel.
  • However, we can use it over a multithreaded kernel. -> In this case, the
    outcome will be the same as running over a non-multithreaded kernel.
  1. Kernel-level thread library
  • Provides a library supported directly by the kernel (i.e., mapping).
  • Code and data structures for the library exist in kernel space.
  • Invoking an API function typically results in a system call to the kernel.
  • Multithreading model (mapping model) depends on the OS types.

Process and Threaded Models

4.Threading Issues

Multi-threaded 프로그램을 디자인할 때 고려해야 할 몇 가지

  1. Semantics of fork( ) and exec( ) system calls
  • 만약 fork( ) 이후에 exec( )을 바로 호출한다면 exec( )으로 인해 스레드를 포함한 전체 프로세스가 대체되기 때문에 모든 스레드를 복제하는 것은 불필요할 것이다. 그렇지 않으면 모든 프로세스를 복제해야 한다.

  • 따라서 몇몇 UNIX 시스템은 두 버전의 fork( )를 가진다. -> 무엇이 더 효율적인지 모르기 때문에

  1. Signal Handling
  • 시그널(Signal)은 특정한 사건이 발생했다고 프로세스에게 알려주기 위해 UNIX 시스템에서 사용하는 것이다.

  • 자원이나 시그널의 원인에 따라 두 종류로 나뉜다.
    1) Synchronous signals

    • 시그널을 일으킨 작업을 수행한 프로세스에 전달된다. (ex. division by 0, illegal memory access)

    2) Asynchronous signals

    • 수행중인 프로세스의 외부 사건에 의해 만들어진다. (ex. Ctrl+C과 같은 특정 키 입력으로 인한 종료, 타이머 종료)
  • 시그널을 다루는 방법(Signal Handling) 또한 다양하다.

    싱글 스레드 프로그램에서는 시그널이 특정 사건에 의해 생성되고, 프로세스에 전달된 후 다뤄진다.

  • 멀티 스레드 프로그램에서는
    시그널을 제공한 스레드로 시그널이 전달되거나(ex. Synchronous signals),
    프로세스 내의 모든 스레드에 전달되거나(ex. process termination signal),
    프로세스 내의 특정한 스레드에 전달될 수 있다(some asynchronous signals to non-blocking threads).
    혹은 프로세스의 모든 시그널을 전달받는 특별한 스레드를 할당하는 방법도 있다.

  1. Thread Cancellation
    스레드가 끝나기 전에 종료시키는 두 방식이 있다.
    1) Asynchronous cancellation : 목표 스레드(Target thread)를 즉시 종료시킨다.

    2) Deferred cancellation : 목표 스레드가 종료되어야 하는지 주기적으로 체크한다.

  2. Thread Pools
    스레드를 요청할 때마다 매번 새로운 스레드를 생성, 수행, 삭제를 반복하면 성능이 저하된다. 따라서 미리 스레드 풀(Thread pools)에 여러 스레드를 만들어두고 요청이 오면 스레드 풀에 기존에 존재하던 스레드를 할당해주는 방법을 사용한다.

  • 새 스레드를 만드는 것보다 기존에 존재하는 스레드를 사용하는 것이 약간 더 빠르고, 많은 양의 스레드를 일정한 크기의 pool 안에 묶어둘 수 있는 장점이 있다.
  1. Thread Local Storage
    각각의 스레드들이 자신의 영역을 만들어 관리할 수 있도록 해주는 것이다. static data와 유사하다.
    Most thread libraries and compilers provide support for TLS.

0개의 댓글