운영체제 | 스레드

Jihun Kim·2021년 10월 28일
0

운영체제

목록 보기
4/5
post-thumbnail

Thread

  • LWP(Lightweight Process)
  • 가장 기본적으로 CPU를 점유하는 단위
  • pid 대신 프로세스 안의 thread id가 cpu를 점유하게 된다.
    👉 program counter, register set, stack 역시 프로그램 별로 달라져야 한다.
    👉 따라서, 별도의 관리가 필요하게 된다.
  • 한 프로세스에 스레드가 여러개면 multi-thread가 된다.

Multi-threading

서버에 새로운 연결이 들어오면 서버는 새로운 thread를 생성해서 thread에게 일을 맡기고, non-blocking으로 resume을 해서 thread가 생성할 수 있는 한도까지 계속 생성 된다.
👉 대부분의 현대적인 소프트웨어들은 multi-threading을 지원한다.
👉 가령, 서버에 클라이언트가 연결을 시도하고 서버가 이를 허용하면 서버에는 새로운 thread가 생성된다.

장점

  1. Responsiveness: User interface를 처리할 때 non-blocking으로 execution을 계속 실행할 수 있다.
  2. Resource Sharing: Process끼리 IPC를 할 때 shared-memory 혹은 o/s의 message-queue를 사용해 데이터를 주고 받았는데, 스레드는 이미 code와 data 영역을 공유하고 있기 때문에 shared-memory를 만들지 않아도 되어 resource 사용이 자유롭다.
  3. Economy: 프로세스 하나 생성하는 것보다 더 쉬우며 context switching시 PCB의 switching과 thread의 switching을 비교해 보았을 때 thread가 훨씬 간단하다.
  4. Scalability(확장성): core가 여러개인 경우(multiprocessor) 각각의 스레드를 붙여 병렬 처리 하는 것이 가능해진다.
  • 스레드는 자바에서 사용하는 것이 용이하다.
    👉 스레드를 생성, 관리하는 것이 자바에서 편하게 이루어진다.

자바에서의 스레드 활용

  1. Thread class를 상속 받는다.
    👉 이후 public void run() method를 override 해준다.
    👉 자바에서는 다중 상속이 되지 않으므로, 스레드 상속 받으면 다른 것을 상속 받을 수가 없다. 따라서 아래의 방법이 더 좋은 방법이다.

  2. Runnable interface를 implement 한다.
    👉 이후 Thread class에서와 마찬가지로 public void run() method를 override 해준다.
    👉 가장 많이 사용하는 방법이다.

  3. Lambda expression을 이용한다.
    👉 비교적 최근 나온 방법으로, '익명 스레드'를 이용하는 방법이다.
    👉 새로운 클래스를 선언하지 않고 Runnable interface를 구현한다.

Multicore system에서의 Multithreading

  • multicore 내에서는 concurrency가 훨씬 향상된다.
    👉 각 코어 내에서 스레드가 cpu를 독점하면 되기 때문이다.

네 개의 스레드가 있다고 해보자

  • single-core에서는 시간에 따라 'interleaving'을 해야 한다. 즉,끝나는 시간에 따라 사이사이 끼워 넣는 것이다.
  • multiple-cores에서는 스레드들이 병렬적으로 실행될 수 있다.

Multicore programming에서 발생하는 문제

👉 Multicore programming을 할 경우 복잡성에 의해 여러 문제가 발생할 수 있다.

  1. 어떤 부분이 독립적으로(병렬적으로) 실행될 수 있는 지를 찾아내는 능력이 필요하다.
  2. 밸런스를 맞춰 주어야 한다.
    👉 각 스레드가 비슷한 양의 일을 하도록 해주어야 한다.
  3. 독립적인 코어에서 실행될 수 있도록 데이터가 분리되어야 한다.
  4. 데이터들의 독립성도 고려해야 한다. 즉, 동기화가 잘 되어야 한다.
  5. 테스트와 디버깅이 어려워진다.

Parallelism 유형
1. Data parallelism: 데이터를 각 코어에 쪼개줌
2. Task parallelism: 데이터는 하나로 두고 task를 쪼갠다.
👉 현재는 분산 시스템(클라우드 시스템과 같은)이 있어 이를 구분할 필요가 없어졌다.

Amdahl's Law(암달의 법칙)

코어는 무조건 많을수록 좋은가?

  • 이 법칙에 의하면 코어가 2배 증가해도 속도가 2배 증가하지는 않는다.
  • 즉, 전부 다 병렬처리가 가능한 것이 아니라면 코어가 증가하는 의미가 없다.


멀티 스레딩

스레드의 두 가지 타입

User thread(사용자 모드에서 사용하는 스레드)
👉 자바와 같이 스레드를 만들어서 사용할 수 있는 것
Kernel thread(커널 모드에서 사용하는 스레드)
👉 운영체제의 스레드

  1. User threads
  • 커널 모드 위에서 스레딩 하는 것을 말함
  1. Kernel threads
  • os가 직접 관리하는 스레드

유저 스레드와 커널 스레드의 관계

  • 커널 스레드는 많은 유저 스레드를 감당할 수 있음
  • 유저 스레드 한 개에 커널 스레드 하나를 맵핑할 수 있음
  • 다양한 유저 스레드와 다양한 커널 스레드를 맵핑할 수도 있음

Thread library

  • 스레드를 생성하고 관리하는 API이다.
  • 세 가지 많이 사용되는 라이브러리가 있다.
  1. POSIX Pthreads(Unix 계열에서 많이 사용)
  • POSIX 표준으로 표준화 되어 있음
  1. Windows thread
  2. Java thread(운영체제에 종속되어 있다.)


Implicit threading

  • concurrent 하며 parallel한 application을 디자인 하는 것은 매우 어렵다.
    👉 이 때문에 implicit threading은 이를 라이브러리가 알아서 해주도록 만드는 것이다.(java.concurrent)

4가지 방법

  1. Thread pools
  • thread pool에 저장해 놓고 필요할 경우 꺼내서 실행한다.
    👉 아래와 같은 명령어를 통해 사용할 수 있다.
ThreadPool.getThreads
  1. Fork & Join
  • join은 wait와 같은 역할이다.
  • 이는 explicit threading에도 사용되었지만 implicit threading에서도 사용된다.
  1. OpenMP
  • 컴파일러 지시어를 이용해 C나 C++에서 병렬처리 할 수 있도록 지원해 준다.
  1. Grand Central Dispatch(GCD)
  • Apple에서 쓰는 것이다.

OpenMP

parallel region만 지정해 주면 그 코드 블럭을 알아서 병렬적으로 실행시킨다.

  • 그동안 라이브러리를 이용해 지시를 했지만, openMP는 compiler에게 어디가 병렬적으로 돌아가야 하는 곳인지를 알려준 뒤 일을 하도록 지시한다.
  • 그러면 openMP 라이브러리가 해당하는 부분에 대한 스레드를 만들어 준다.
profile
쿄쿄

0개의 댓글