Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
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
Tags
more
Archives
Today
Total
관리 메뉴

개발자입니다

[비트캠프] 63일차(13주차5일) - Java(네트워킹 연결방식, 스레드), myapp-33~35 본문

네이버클라우드 AIaaS 개발자 양성과정 1기/Java

[비트캠프] 63일차(13주차5일) - Java(네트워킹 연결방식, 스레드), myapp-33~35

끈기JK 2023. 2. 3. 11:32

 

myapp

 

 

Networking 연결 방식

 

  • Connection-Oriented (연결 지향)
    예) 전화; WoW, LOL, 구글 미트, 웹메일
    프로토콜 → TCP
    • Stateful  예) 상담 전화
      프로토콜 : SSH, Telnet, FTP, 채팅
      연결 → 요청, 응답 반복 → 끊기
    • Stateless  예) 114 안내
      프로토콜 : HTTP 1, HTTP 2
      연결 → 요청, 응답 1번 → 끊기
  • Connectionless (비연결성)
    예) 방송, 편지, 택배; ping
    프로토콜 → UDP

 

Connection-Oriented : 연결하는 과정에서 시간을 소요, 연결한 후 데이터 전송 → 신뢰성 보장

Connectionless : 연결 과정이 없다 → 시간 절약, 연결 확인 없이 데이터 전송 → 신뢰성 낮다.

 

(TCP) HTTP 1/2 → (UDP) HTTP 3

 

 

 

Stateful 방식과 Stateless 방식 비교

 

-Stateful

요청과 응답을 반복한다.

뒤에서는 먼저 접속한 client가 연결을 끊을 때까지 대기.

한 클라이언트가 오랜 시간 연결되어 있으면 다른 클라이언트들의 대기 시간이 길어진다.

 

-Stateless

요청과 응답을 1번만 수행한다. 서버의 응답을 받으면 연결을 끊는다.

한 번 연결에 한 번의 요청/응답만 처리한다. 다른 클라이언트의 연결 대기 시간이 적다. 더 많은 클라이언트의 요청을 처리

 

 

 

33. Stateful → Stateless

 

### 33. 통신 방식을 Stateful에서 Stateless로 변경하기 
- Stateful과 Stateless 방식의 차이점 이해 
- Stateless 방식으로 통신하는 방법

 

NetworkBoardDao 에서 Server 로 ① 연결 ② 요청 하면 Server 에서 NetworkBoardDao 로 ③ 응답 한다. 그러면 NetworkBoardDao 에서 ④ 연결 종료 한다.

 

요청할 때마다 연결한다. 응답 후 연결 끊는다. 더 많은 클라이언트에 대응할 수 있다.

 

 

ServerApp 의 processRequest() 메서드에서 while 문을 제거한다.

public class ServerApp {

  BoardDao boardDao = new BoardDao(new LinkedList<Board>());
  StudentDao studentDao = new StudentDao(new ArrayList<Student>());
  TeacherDao teacherDao = new TeacherDao(new ArrayList<Teacher>());

  StudentServlet studentServlet = new StudentServlet(studentDao);
  TeacherServlet teacherServlet = new TeacherServlet(teacherDao);
  BoardServlet boardServlet = new BoardServlet(boardDao);

  public static void main(String[] args) {
    new ServerApp().service(8888);
    System.out.println("서버 종료!");
  }

  void service(int port) {

    System.out.println("서버 실행 중...");

    try (ServerSocket serverSocket = new ServerSocket(port)) {

      boardDao.load("board.json");
      studentDao.load("student.json");
      teacherDao.load("teacher.json");

      while (true) {
        processRequest(serverSocket.accept());
      }

    } catch (Exception e) {
      System.out.println("서버 오류 발생!");
      e.printStackTrace();
    }
  }

  void processRequest(Socket socket) {
    try (Socket socket2 = socket;
        DataInputStream in = new DataInputStream(socket.getInputStream());
        DataOutputStream out = new DataOutputStream(socket.getOutputStream())) {

      InetAddress address = socket.getInetAddress();
      System.out.printf("%s 가 연결함!\n", address.getHostAddress());

      String dataName = in.readUTF();
      switch (dataName) {
        case "board":
          boardServlet.service(in, out);
          boardDao.save("board.json");
          break;
        case "student":
          studentServlet.service(in, out);
          studentDao.save("student.json");
          break;
        case "teacher":
          teacherServlet.service(in, out);
          teacherDao.save("teacher.json");
          break;
      }
    } catch (Exception e) {
      System.out.println("실행 오류!");
    }
  }
}

 

app-common 에 dao 패키지 생성 후 DaoStub 클래스 만든다.

Netwrok----Dao 에서 fetch 부분 가져온다.

public class DaoStub {

  String ip;
  int port;

  public DaoStub(String ip, int port) {
    this.ip = ip;
    this.port = port;
  }

  public String fetch(String dataName, String action, Object... data)
      throws DaoException {
    try (Socket socket = new Socket(ip, port);
        DataOutputStream out = new DataOutputStream(socket.getOutputStream());
        DataInputStream in = new DataInputStream(socket.getInputStream())) {

      out.writeUTF(dataName);
      out.writeUTF(action);

      if (data.length > 0) {
        out.writeUTF(new Gson().toJson(data[0]));
      }

      // 응답
      String status = in.readUTF();
      if (status.equals("400")) {
        throw new DaoException("클라이언트 요청 오류!");
      } else if (status.equals("500")) {
        throw new DaoException("서버 실행 오류!");
      }
      return in.readUTF();

    } catch (DaoException e) {
      throw e;
    } catch (Exception e) {
      throw new DaoException("오류 발생!", e);
    }
  }
}

app-common 의 dao 에 DaoException 옮겨온다.

 

ip, port 입력해서 DaoStub 생성 후 Network---Dao 생성시 주입한다.

public class ClientApp {

  public static void main(String[] args) {
    new ClientApp().execute("localhost", 8888);
  }

  void execute(String ip, int port) {
    try {
      DaoStub daoStub = new DaoStub(ip, port);
      NetworkBoardDao boardDao = new NetworkBoardDao(daoStub);
      NetworkStudentDao studentDao = new NetworkStudentDao(daoStub);
      NetworkTeacherDao teacherDao = new NetworkTeacherDao(daoStub);

      StudentHandler studentHandler = new StudentHandler("학생", studentDao);
      TeacherHandler teacherHandler = new TeacherHandler("강사", teacherDao);
      BoardHandler boardHandler = new BoardHandler("게시판", boardDao);

      loop: while (true) {
        System.out.println("1. 학생관리");
        System.out.println("2. 강사관리");
        System.out.println("3. 게시판");
        System.out.println("9. 종료");

        int menuNo;
        try {
          menuNo = Prompt.inputInt("메뉴> ");
        } catch (Exception e) {
          System.out.println("메뉴 번호가 옳지 않습니다!");
          continue;
        }

        try {
          switch (menuNo) {
            case 1:
              studentHandler.service();
              break;
            case 2:
              teacherHandler.service();
              break;
            case 3:
              boardHandler.service();
              break;
            case 9:
              break loop; // loop 라벨이 붙은 while 문을 나간다.
            default:
              System.out.println("잘못된 메뉴 번호 입니다.");
          }
        } catch (Exception e) {
          System.out.printf("명령 실행 중 오류 발생! - %s : %s\n",
              e.getMessage(),
              e.getClass().getSimpleName());
        }
      }

      System.out.println("안녕히 가세요!");

      Prompt.close();

    } catch (Exception e) {
      System.out.println("네트워킹 오류!");
      e.printStackTrace();
    }
  }
}

 

NetworkBoardDao 에 DaoStub 변수 선언하고 생성자 아규먼트로 받는다.

Teacher, Student 도 동일하게 변경한다.

public class NetworkBoardDao implements BoardDao {

  DaoStub daoStub;

  public NetworkBoardDao(DaoStub daoStub) {
    this.daoStub = daoStub;
  }

  @Override
  public void insert(Board b) {
    daoStub.fetch("board", "insert", b);
  }

  @Override
  public Board[] findAll() {
    return new Gson().fromJson(daoStub.fetch("board", "findAll"), Board[].class);
  }

  @Override
  public Board findByNo(int no) {
    return new Gson().fromJson(daoStub.fetch("board", "findByNo", no), Board.class);
  }

  @Override
  public void update(Board b) {
    daoStub.fetch("board", "update", b);
  }

  @Override
  public boolean delete(Board b) {
    daoStub.fetch("board", "delete", b);
    return true;
  }
}

 

 

 

34. 여러 클라이언트의 요청을 동시에 처리하는 방법

 

### 34. Thread를 이용한 멀티 태스킹 구현하기: 동시 요청 처리하기 
- Thread로 멀티 태스킹을 구현하는 방법 
- 멀티 태스킹의 이해 
- 멀티 프로세스와 멀티 스레드의 구동 원리 이해

 

① 현재 상황

"main" 스레드가 클라이언트 요청을 순차적으로 처리한다.

 

② 멀티 스레드 적용

"main" 스레드가 접수받는 역할만 한다. Client1이 ① 접속 하면 스레드1 을 ② 생성 하면, 스레드1이 ③ 요청, ④ 응답을 처리한다. Client 2,3 도 마찬가지다.

 

여러 스레드를 동원하여 여러 클라이언트 요청을 "동시 처리"

 

 

 

 

Thread

 

 

스레드 생성 및 실행

 

① 서브 클래스 만들기

MyThread 가 Thread 를 상속한다. MyThread 객체 생성해서 t.start() 메서드 실행한다.

 

② 익명 클래스로 서브 클래스 만들기

Thread 객체 생성하고 익명 클래스로 서브클래스 바로 정의한다. 그리고 run() 메서드 정의한다. 뒤에 start() 메서드 실행한다.

 

 

③ Runnable 구현체 만들기

《interface》Runnable 을 구현한 MyRunnable 이 있다. Thread t 객체 생성하며 생성자 아규먼트에 Runnable 객체 전달한다. 그리고 t.start() 실행한다.

 

④ 익명 클래스로 Runnable 구현

Thread 객체 생성하며 생성자 아규먼트에 Runnable 객체 생성하고 익명 클래스로 서브클래스 바로 정의한다. 그리고 run() 메서드 구현한다. 뒤에 start() 메서드 실행한다.

 

 

public class ServerApp0 {

  BoardDao boardDao = new BoardDao(new LinkedList<Board>());
  StudentDao studentDao = new StudentDao(new ArrayList<Student>());
  TeacherDao teacherDao = new TeacherDao(new ArrayList<Teacher>());

  StudentServlet studentServlet = new StudentServlet(studentDao);
  TeacherServlet teacherServlet = new TeacherServlet(teacherDao);
  BoardServlet boardServlet = new BoardServlet(boardDao);

  public static void main(String[] args) {
    new ServerApp().service(8888);
    System.out.println("서버 종료!");
  }

  void service(int port) {
    System.out.println("서버 실행 중...");

    try (ServerSocket serverSocket = new ServerSocket(port)) {

      boardDao.load("board.json");
      studentDao.load("student.json");
      teacherDao.load("teacher.json");

      while (true) {
        new RequestProcessorThread(serverSocket.accept()).start(); // 스레드를 실행시킨다.
      }

    } catch (Exception e) {
      System.out.println("서버 오류 발생!");
      e.printStackTrace();
    }
  }

  class RequestProcessorThread extends Thread {
    Socket socket;

    public RequestProcessorThread(Socket socket) {
      this.socket = socket;
    }

    @Override
    public void run() {
      // 스레드를 통해 독립적으로 실행시키고 싶은 코드가 있다면
      // run() 메서드 안에 두어라!
      // 또는 run() 메서드에서 해당 코드를 호출하도록 만들어라!
      //
      try (Socket socket2 = socket;
          DataInputStream in = new DataInputStream(socket.getInputStream());
          DataOutputStream out = new DataOutputStream(socket.getOutputStream())) {

        InetAddress address = socket.getInetAddress();
        System.out.printf("%s 가 연결함!\n", address.getHostAddress());

        String dataName = in.readUTF();
        switch (dataName) {
          case "board":
            boardServlet.service(in, out);
            boardDao.save("board.json");
            break;
          case "student":
            studentServlet.service(in, out);
            studentDao.save("student.json");
            break;
          case "teacher":
            teacherServlet.service(in, out);
            teacherDao.save("teacher.json");
            break;
        }
      } catch (Exception e) {
        System.out.println("실행 오류!");
      }
    }
  }
}

 

public class ServerApp1 {

  BoardDao boardDao = new BoardDao(new LinkedList<Board>());
  StudentDao studentDao = new StudentDao(new ArrayList<Student>());
  TeacherDao teacherDao = new TeacherDao(new ArrayList<Teacher>());

  StudentServlet studentServlet = new StudentServlet(studentDao);
  TeacherServlet teacherServlet = new TeacherServlet(teacherDao);
  BoardServlet boardServlet = new BoardServlet(boardDao);

  public static void main(String[] args) {
    new ServerApp1().service(8888);
    System.out.println("서버 종료!");
  }

  void service(int port) {
    System.out.println("서버 실행 중...");

    try (ServerSocket serverSocket = new ServerSocket(port)) {

      boardDao.load("board.json");
      studentDao.load("student.json");
      teacherDao.load("teacher.json");

      while (true) {
        Socket socket = serverSocket.accept();
        new Thread() {
          @Override
          public void run() {
            processRequest(socket);
          };
        }.start(); // 스레드를 실행시킨다.
      }

    } catch (Exception e) {
      System.out.println("서버 오류 발생!");
      e.printStackTrace();
    }
  }

  void processRequest(Socket socket) {
    try (Socket socket2 = socket;
        DataInputStream in = new DataInputStream(socket.getInputStream());
        DataOutputStream out = new DataOutputStream(socket.getOutputStream())) {

      InetAddress address = socket.getInetAddress();
      System.out.printf("%s 가 연결함!\n", address.getHostAddress());

      String dataName = in.readUTF();
      switch (dataName) {
        case "board":
          boardServlet.service(in, out);
          boardDao.save("board.json");
          break;
        case "student":
          studentServlet.service(in, out);
          studentDao.save("student.json");
          break;
        case "teacher":
          teacherServlet.service(in, out);
          teacherDao.save("teacher.json");
          break;
      }
    } catch (Exception e) {
      System.out.println("실행 오류!");
    }
  }

}

 

public class ServerApp2 {

  BoardDao boardDao = new BoardDao(new LinkedList<Board>());
  StudentDao studentDao = new StudentDao(new ArrayList<Student>());
  TeacherDao teacherDao = new TeacherDao(new ArrayList<Teacher>());

  StudentServlet studentServlet = new StudentServlet(studentDao);
  TeacherServlet teacherServlet = new TeacherServlet(teacherDao);
  BoardServlet boardServlet = new BoardServlet(boardDao);

  public static void main(String[] args) {
    new ServerApp2().service(8888);
    System.out.println("서버 종료!");
  }

  void service(int port) {
    System.out.println("서버 실행 중...");

    try (ServerSocket serverSocket = new ServerSocket(port)) {

      boardDao.load("board.json");
      studentDao.load("student.json");
      teacherDao.load("teacher.json");

      while (true) {
        Socket socket = serverSocket.accept();
        new Thread(new RequestProcessor(socket)).start();
      }

    } catch (Exception e) {
      System.out.println("서버 오류 발생!");
      e.printStackTrace();
    }
  }

  void processRequest(Socket socket) {
    try (Socket socket2 = socket;
        DataInputStream in = new DataInputStream(socket.getInputStream());
        DataOutputStream out = new DataOutputStream(socket.getOutputStream())) {

      InetAddress address = socket.getInetAddress();
      System.out.printf("%s 가 연결함!\n", address.getHostAddress());

      String dataName = in.readUTF();
      switch (dataName) {
        case "board":
          boardServlet.service(in, out);
          boardDao.save("board.json");
          break;
        case "student":
          studentServlet.service(in, out);
          studentDao.save("student.json");
          break;
        case "teacher":
          teacherServlet.service(in, out);
          teacherDao.save("teacher.json");
          break;
      }
    } catch (Exception e) {
      System.out.println("실행 오류!");
    }
  }

  class RequestProcessor implements Runnable {
    Socket socket;

    public RequestProcessor(Socket socket) {
      this.socket = socket;
    }

    @Override
    public void run() {
      ServerApp2.this.processRequest(socket);
    }
  }
}

 

package bitcamp.myapp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.LinkedList;
import bitcamp.myapp.dao.BoardDao;
import bitcamp.myapp.dao.StudentDao;
import bitcamp.myapp.dao.TeacherDao;
import bitcamp.myapp.servlet.BoardServlet;
import bitcamp.myapp.servlet.StudentServlet;
import bitcamp.myapp.servlet.TeacherServlet;
import bitcamp.myapp.vo.Board;
import bitcamp.myapp.vo.Student;
import bitcamp.myapp.vo.Teacher;

public class ServerApp3 {

  BoardDao boardDao = new BoardDao(new LinkedList<Board>());
  StudentDao studentDao = new StudentDao(new ArrayList<Student>());
  TeacherDao teacherDao = new TeacherDao(new ArrayList<Teacher>());

  StudentServlet studentServlet = new StudentServlet(studentDao);
  TeacherServlet teacherServlet = new TeacherServlet(teacherDao);
  BoardServlet boardServlet = new BoardServlet(boardDao);

  public static void main(String[] args) {
    new ServerApp3().service(8888);
    System.out.println("서버 종료!");
  }

  void service(int port) {
    System.out.println("서버 실행 중...");

    try (ServerSocket serverSocket = new ServerSocket(port)) {

      boardDao.load("board.json");
      studentDao.load("student.json");
      teacherDao.load("teacher.json");

      while (true) {
        Socket socket = serverSocket.accept();
        new Thread(new Runnable() {
          @Override
          public void run() {
            processRequest(socket);
          }
        }).start();
      }

    } catch (Exception e) {
      System.out.println("서버 오류 발생!");
      e.printStackTrace();
    }
  }

  void processRequest(Socket socket) {
    try (Socket socket2 = socket;
        DataInputStream in = new DataInputStream(socket.getInputStream());
        DataOutputStream out = new DataOutputStream(socket.getOutputStream())) {

      InetAddress address = socket.getInetAddress();
      System.out.printf("%s 가 연결함!\n", address.getHostAddress());

      String dataName = in.readUTF();
      switch (dataName) {
        case "board":
          boardServlet.service(in, out);
          boardDao.save("board.json");
          break;
        case "student":
          studentServlet.service(in, out);
          studentDao.save("student.json");
          break;
        case "teacher":
          teacherServlet.service(in, out);
          teacherDao.save("teacher.json");
          break;
      }
    } catch (Exception e) {
      System.out.println("실행 오류!");
    }
  }
}

 

public class ServerApp {

  BoardDao boardDao = new BoardDao(new LinkedList<Board>());
  StudentDao studentDao = new StudentDao(new ArrayList<Student>());
  TeacherDao teacherDao = new TeacherDao(new ArrayList<Teacher>());

  StudentServlet studentServlet = new StudentServlet(studentDao);
  TeacherServlet teacherServlet = new TeacherServlet(teacherDao);
  BoardServlet boardServlet = new BoardServlet(boardDao);

  public static void main(String[] args) {
    new ServerApp().service(8888);
    System.out.println("서버 종료!");
  }

  void service(int port) {

    System.out.println("서버 실행 중...");

    try (ServerSocket serverSocket = new ServerSocket(port)) {

      boardDao.load("board.json");
      studentDao.load("student.json");
      teacherDao.load("teacher.json");

      while (true) {
        Socket socket = serverSocket.accept();
        new Thread(() -> processRequest(socket)).start();
      }

    } catch (Exception e) {
      System.out.println("서버 오류 발생!");
      e.printStackTrace();
    }
  }

  void processRequest(Socket socket) {
    try (Socket socket2 = socket;
        DataInputStream in = new DataInputStream(socket.getInputStream());
        DataOutputStream out = new DataOutputStream(socket.getOutputStream())) {

      InetAddress address = socket.getInetAddress();
      System.out.printf("%s 가 연결함!\n", address.getHostAddress());

      String dataName = in.readUTF();
      switch (dataName) {
        case "board":
          boardServlet.service(in, out);
          boardDao.save("board.json");
          break;
        case "student":
          studentServlet.service(in, out);
          studentDao.save("student.json");
          break;
        case "teacher":
          teacherServlet.service(in, out);
          teacherDao.save("teacher.json");
          break;
      }
    } catch (Exception e) {
      System.out.println("실행 오류!");
    }
  }
}

 

 

 

멀티 태스킹 (Multi-tasking)

 

① Single-tasking

CPU 가 App 을 실행하면 나머지 App 은 대기한다. 예) DOS

CPU 를 100% 활용 불가

 

사례1) 종업원이 손님1에게만 주문, 세팅, 서빙 한다.

한 번에 한 손님만 서비스 하면 손님1의 서비스가 끝날 때 까지 대기하므로 종업원(인력) 낭비!

 

사례2) 요리사에게 주문으로 짜장면1, 짬뽕1, 볶음밥1 이 들어오면 하나씩 요리한다.

① 짜장면을 다 만들고 나서 ② 짬뽕을 만들고 ③ 볶음밥을 만든다.

순차적으로 실행 → 주방장 월급이 아깝다.

 

 

② Multi-tasking

시간을 쪼개서 여러 App을 돌아다니면서 명령어를 실행 = 시분할 시스템

여러 App 이 동시 실행하는 것처럼 보인다. 예) Windows, Unix

 

사례1) 종업원이 손님1, 2, 3 에게 동시에 주문, 세팅, 서빙을 한다. 시간을 쪼개서 여러 손님을 응대

사례2) 요리사가 짜장면, 짬뽕, 볶음밥을 동시에 만든다. 시간을 쪼개서 여러 작업을 돌아가면서 실행

 

 

 

다중 클라이언트 요청 처리에 멀티 태스킹 적용

 

① 프로세스 복제 방식 (fork())

Client 1 이 Server 에 ① 접속하면 Server'로 ② fork (복제) 한다. 이 Server' 가 ③ 요청/응답 한다. Server 의 Heap, Stack 메모리를 복제한다.

Client 2 가 Server 에 ① 접속하면 Server''로 ② fork (복제) 한다. 이 Server'' 가 ③ 요청/응답 한다. Server 의 Heap, Stack 메모리를 복제한다.

Server 를 부모 프로세스, Server', Server'' 를 자식 프로세스라 한다.

 

문제점

① 프로세스(서버 프로그램)가 사용하는 메모리도 그대로 복제 → 메모리 낭비가 심하다.

② 부모 프로세스를 종료 하더라도 자식 프로세스는 종료되지 않는다. → 복제한 자식 프로세스를 제어하기 힘들다.

 

 

② 멀티스레드 방식

Client 1 이 Server 에 ① 접속 하면 ② 스레드 생성한다. 스레드가 ③ 요청/응답 한다. Server 의 Stack 메모리를 Thread에 복제한다. 이 메모리는 스레드가 작업하는 동안 사용할 메모리이다. Heap 메모리는 Server 와 공유한다.

Client 2 가 Server 에 ① 접속 하면 ② 스레드 생성한다. 스레드가 ③ 요청/응답 한다. Server 의 Stack 메모리를 Thread에 복제한다. 이 메모리는 스레드가 작업하는 동안 사용할 메모리이다. Heap 메모리는 Server 와 공유한다.

 

특징

① 프로세스의 Heap 메모리 공유 → 객체를 중복 생성하지 않는다 → 메모리 낭비가 적다

② 프로세스 종료 → 스레드 종료 → 스레드는 프로세스에 종속된다.

 

 

 

JVM 과 스레드

 

JVM (java.exe) 을 실행한다. JVM 은 프로세스이다. start() 하면 《Thread》main 이 실행된다. main 쓰레드가 main() 메서드를 call 한다. main() 에서 실행 되다가 다른 곳 갔다가 돌아오는 걸 반복하고 종료된다.

실행 흐름이 한 줄로 이어진 실타래와 같아서 "Thread"라 부른다!

 

 

 

부모 스레드와 자식 스레드

 

부모 스레드인 《Thread》main 에서 main() 메서드를 call 한다. main() 에서 new Thread() 하면 새 Thread (자식 스레드)가 생성된다. start() 하면 run() 메서드가 실행된다.

 

 

 

CPU Scheduling

 

프로세스에게 CPU 를 배정하는 방법

OS가 프로세스의 명령을 실행하는 순서나 시간을 제어한다.

① Round-Robin (Windows OS)

    모든 프로세스를 동일한 시간으로 나눠 실행한다.

    우선 순위가 실행에 영향을 덜 끼친다.

② Priority + Aging 기법 (Linux, Unix)

    우선 순위가 높은 프로세스에게 실행 횟수나 시간을 더 부여한다.

    우선 순위가 실해엥 영향을 끼친다.

 

 

 

CPU Scheduling 과 스레드

 

프로세스가 스레드 T1, T2, T3 를 생성한다.

OS 는 스레드에 대해서도 프로세스와 동일한 자격으로 스케줄링 한다.

프로세스가 받은 시간을 스레드가 나눠 사용하는 것이 아니다!

 

 

 

CPU 스케줄링과 Context Switching

 

Context Switching : 실행 정보와 명령을 CPU 캐시 메모리에 적재하는 것

CPU 안에 L1, L2 캐시가 있다. L1 에는 명령어, L2 에는 데이터를 저장한다.

프로세스 A, B, C, ... 가 있고 OS 가 A 를 ① 실행 하면 ② 캐시메모리에 적재 한다. B 를 ③ 실행 하면 캐시메모리에 ④ 적재 한다. 기존 프로세스 실행정보는 캐시메모리에 보관된다.

 

Context Switching

CPU 스케줄링 정책에 따라 프로세스를 돌아가면서 실행할 때, 이전 프로세스의 실행 정보를 보관 → 다른 프로세스의 실행 정보를 적재한다.

너무 짧은 시간동안 너무 자주 프로세스를 교체하면 명령을 실행하는 시간보다 Context Switching 시간이 더 많이 소요되기 때문에 비효율적이 된다. 그래서 적절한 시간에 따라 프로세스를 교체해야 한다.

 

 

 

Critical Region = Critical Section

 

여러 스레드가 동시에 실행할 때 문제가 발생할 수 있는 코드 영역 → synchronized 를 사용하여 동시 진입을 제어한다.

Critical Section : 여러 사람이 동시에 진입할 때 문제 발생! Semaphore(1) = "Mutex"

Critical Section : Semaphore(5)  *Semaphore: 동시진입 제어하는 것

 

Mutual Exclusion (상호 배제)

3개 중에 오직 1단계만 선택 가능. 한 개 선택하면 다른 단계는 취소된다.

예) 라디오 채널, TV 채널

Mutex → 오직 한 개만 선택!

 

 

 


 

 

조언

 

*현업 하고 나서 컴공과 수업 들으면 와닿는다. 개발 업무 하면서 네트워킹 책 보면서 바닥을 다져야 한다. 유닉스의 탄생 책 꼭 봐라.

*분석 설계자는 코드를 한 줄씩 바라보는게 아니라, 객체를 사람으로 보고 메서드를 명령으로 본다. 예) daoStub 한테 fetch 시

 

 


 

과제

 

학습

-com.eomcs.concurrent