Home OS Thread (1)
Post
Cancel

OS Thread (1)

목적


  1. CPU 이용의 기본 단위가 된 스레드를 이해한다.

실천 목표


  1. 스레드의 기본 구성요소를 식별하고 스레드와 프로세스를 대조한다.
  2. 다중 스레드 프로세스를 설계할 때의 주요 이점과 중대한 과제를 설명한다.

이제까지의 내용은 사실, 싱글 스레드


  • 프로세스 내 스레드가 1개인 싱글 스레드 2022-10-16-os-thread-01

그렇다면 스레드란


  • 프로세스 내에서 특정 부분을 공유하며 별도로 수행되는 일꾼
  • 경량 프로세스라고 할 수 있으며, CPU를 점유하는 기본적인 단위
  • 한 프로세스 내 스레드가 공유하는 변수들 : code, data, files
  • 스레드 별로 할당되는 변수들 : TID(Thread ID), PC(Program Counter), Register Set, Stack 2022-10-16-os-thread-02

멀티 스레드의 이점


  • 기존 싱글 스레드 2022-10-16-os-thread-03
  • [참고] 기존 싱글 스레드 : Data Server
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    
          package os.concepts;
    
          import java.io.IOException;
          import java.io.OutputStream;
          import java.io.PrintWriter;
          import java.net.ServerSocket;
          import java.net.Socket;
          import java.text.DateFormat;
          import java.text.SimpleDateFormat;
          import java.util.Date;
    
          public class DateServer {
              public static void main(String[] args) throws IOException {
                  ServerSocket serverSocket = null;
                  int port = 7777;
    
                  try {
                      /* 서버 소켓 생성 후 7777번 포트와 결합 */
                      serverSocket = new ServerSocket(port);
                      System.out.printf("%s 서버가 준비되었습니다.\n", getTime());
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
    
                  while (true) {
                      System.out.printf("%s 연결요청을 기다립니다.\n", getTime());
                      /* 서버 소켓은 클라이언트의 연결요청이 올 때까지 실행을 멈추고 기다림 */
                      /* 클라이언트의 연결요청이 들어오면 클라이언트 소켓과 통신할 새로운 소켓 생성 */
                      Socket socket = serverSocket.accept();
                      System.out.printf("%s %s:%d으로부터 연결요청이 들어왔습니다.\n", getTime(), socket.getInetAddress(), socket.getPort());
    
                      /* 소켓의 출력스트림을 얻음 */
                      OutputStream out = socket.getOutputStream();
                      PrintWriter pout = new PrintWriter(out, true);
    
                      /* 원격 소켓에 데이터를 보냄 */
                      pout.printf("%s Message From Server\n", getTime());
    
                      /* 스트림과 소켓을 닫음 */
                      socket.close();
                      pout.close();
                      out.close();
                  }
              }
    
              private static String getTime() {
                  DateFormat df = new SimpleDateFormat("[hh:mm:ss]");
                  return df.format(new Date());
              }
          }
    
  • [참고] 기존 싱글 스레드 : Data Client
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    
          package os.concepts;
    
          import java.io.BufferedReader;
          import java.io.IOException;
          import java.io.InputStream;
          import java.io.InputStreamReader;
          import java.net.ConnectException;
          import java.net.Socket;
          import java.text.DateFormat;
          import java.text.SimpleDateFormat;
          import java.util.Date;
    
          public class DateClient {
              public static void main(String[] args) {
                  try {
                      String serverIp = "127.0.0.1";
                      int serverPort = 7777;
    
                      System.out.printf("%s:%d서버에 연결 중입니다.\n", serverIp, serverPort);
    
                      /* 소켓을 생성해서 연결을 요청 */
                      Socket socket = new Socket(serverIp, serverPort);
    
                      /* 소켓의 입력스트림을 얻음 */
                      InputStream in = socket.getInputStream();
                      BufferedReader br = new BufferedReader(new InputStreamReader(in));
    
                      /* 원격 소켓으로부터 받은 데이터 출력 */
                      System.out.printf("%s 서버로부터 받은 메시지\n", getTime());
                      String line = null;
                      while ((line = br.readLine()) != null)
                          System.out.println(line);
    
                      /* 스트림과 소켓을 닫음 */
                      socket.close();
                      br.close();
                      in.close();
                  } catch (ConnectException ce) {
                      ce.printStackTrace();
                  } catch (IOException ie) {
                      ie.printStackTrace();
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
    
              private static String getTime() {
                  DateFormat df = new SimpleDateFormat("[hh:mm:ss]");
                  return df.format(new Date());
              }
          }
    
  • 웹 서버의 서버-클라이언트 시스템이 멀티 스레드의 대표적인 예 2022-10-16-os-thread-04 2022-10-16-os-thread-05 Copyrightⓒ2022 <CentOS 7으로 리눅스마스터 1급 정복하기>, 정성재, 북스홀릭 All rights reserved. 2022-10-16-os-thread-06 Copyrightⓒ2022 <CentOS 7으로 리눅스마스터 1급 정복하기>, 정성재, 북스홀릭 All rights reserved.
  • 그래서, 멀티 스레드의 이점 4가지
    1. 응답성 (Responsiveness)
      • 특히 사용자 인터페이스에서 중요
    2. 자원 공유 (Resource Sharing)
      • 스레드는 자동으로 그들이 속한 프로세스의 자원들과 메모리를 공유
    3. 경제성 (Economy)
      • 프로세스보다 스레드를 생성하고 문맥 교환하는 게 경제적
    4. 규모 적응성 (Scalability)
      • 멀티 코어 구조에서 멀티 스레드의 이점이 더욱 증가

스레드 프로그래밍 (Java)


  • Java에서는 프로그램 수행의 기본적인 모델이 스레드 2022-10-16-os-thread-07 _Copyrightⓒ2022 , 남궁성, 도우출판 All rights reserved._
  • 스레드 라이브러리를 이용하는 방법은 기본적으로 2가지
    1. Thread 클래스 상속 받기
    2. Runnable 인터페이스 구현하기
      • 불필요하게 클래스를 하나 생성해야 하므로 람다 표현식 이용해서 익명 클래스로 대체 가능
        1. Thread 클래스 상속 받기 2022-10-16-os-thread-10 2022-10-16-os-thread-11
        2. Runnable 인터페이스 구현하기 2022-10-16-os-thread-12 2022-10-16-os-thread-13
        3. Runnable 인터페이스 구현하기 - 람다 표현식 이용해서 익명 클래스로 대체 2022-10-16-os-thread-14
  • 부모 스레드의 대기와 스레드의 종료 2022-10-16-os-thread-12 2022-10-16-os-thread-13

멀티 코어 프로그래밍


  • 멀티 스레드는 멀티 코어 시스템에서 보다 효율적
  • 시분할(Time-sharing) 뿐 아니라 병렬(Parallelism)로 실행되기 때문 2022-10-16-os-thread-08
  • 그러나 멀티 코어 프로그래밍을 하는 것은 복잡한 작업이고, 다음은 이에 대한 5가지 도전 과제
    1. 태스크 인식 (identifying tasks)
      • 응용 프로그램을 분석해서 독립된 병행 가능 태스크로 나눌 수 있는 영역을 찾는 작업
    2. 균형 (balance)
      • 찾아낸 영역들이 균등한 기여도를 가지도록 태스크를 나누는 작업
    3. 데이터 분리 (data spliting)
      • 태스크가 접근하고 조작하는 데이터를 개별 코어에서 사용할 수 있도록 나누는 작업
    4. 데이터 종속성 (data dependency)
      • 태스크가 접근하는 데이터에 대해 둘 이상의 태스크 사이에 종속성이 없는지 검토
    5. 테스트 및 디버깅 (test and debugging)
      • 단일 스레드인 경우보다 테스트 및 디버깅이 어려움
  • 위 문제만 해결한다면, 멀티 코어 시스템에서 코어는 다다익선인가? 2022-10-16-os-thread-09

참고


  1. 운영체제 공룡책 강의 | 주니온 | 인프런 https://www.inflearn.com/course/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EA%B3%B5%EB%A3%A1%EC%B1%85-%EC%A0%84%EA%B3%B5%EA%B0%95%EC%9D%98/dashboard
  2. 운영체제 제 10판Abraham Silberschatz, Peter Baer Galvin, Greg Gagne 저/박민규 역퍼스트북2020년 02월 28일
  3. 운영체제 제 10판 솔루션 https://codex.cs.yale.edu/avi/os-book/OS10/practice-exercises/index-solu.html
This post is licensed under CC BY 4.0 by the author.