Process와 Thread

Queue

  • FIFO(First In, First Out)

  • 선입선출

  • 먼저 들어온 것이 먼저 나가는 방식

    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
    class Queue:
    def __init__(self):
    self.container = list()

    def empty(self):
    if self.container:
    return False
    else:
    return True

    def enqueue(self, data):
    return self.container.append(data)

    def dequeue(self):
    return self.container.pop(0)

    def peek(self):
    return self.container[0]


    if __name__ == '__main__':

    que = Queue()

    for i in range(1, 6):
    que.enqueue(i)

    while not que.empty():
    print(que.dequeue(), end = " ")

    >> 1 2 3 4 5

Computer Engineering

  • Process

    • Program : HDD에 있는 Image

    • Process : “실행중인” RAM에 메모리가 올라왔을 때

    • 같은 프로세스를 켜도 PID(Process ID)가 다르다.

    • 윈도우는 PID가 랜덤으로 생성

    • 리눅스는 PID가 0번부터 순차적으로 생성

    • 프로그램이 실행되면 바로 RAM에 메모리가 생기는 것이 아니라 Run queue로 들어감

  • Process Scheduling

    • CPU에서 프로세스들이 동시에 실행할 수 있게 순위를 조정

    • Priority Algorithm

      • 우선순위를 통해 프로세스 실행

      • 리눅스에서는 nice 값이 높으면 우선순위가 낮아짐

    • Round-Robin Algorithm

      • 모든 프로세스에게 공평하게 시간을 할당해줌

      • 시간(Time Slice, Quantum) = 한 프로세스에 할당되는 시간

    • scheduler 동작시기

      1. 한 프로세스의 time slice가 끝나고 다음 차례일 때

      2. Process created or ended

      3. Running process blocked

        • I/O bound 또는 system call로 인해 blocking이 걸렸을 때

          • I/O bound ex) +, -, *, /, AND(CPU bound)

          • System call ex) sleep()

      • I/O 작업이 끝났다고 해서 바로 running으로 가는 것이 아니다.

      • waiting으로 가서 scheduler를 기다린다.(time slice를 기다림)

      • 리눅스에 top에서 R은 running + waiting = Context Switching

      • 메모리 안에 Process Control Block(PCB)를 만든다.

      • PCB 안에 CPU 레지스터에 있는 값을 모두 복사해둔다.

      • CPU에 있는 레지스터 상태 정보를 Context라고 한다.

    • Context Switching

      • CPU에서 PCB의 정보를 내리고 올리는 작업

      • 너무 자주 context switch를 하면 멀티해보일 수 있으나, 느려질 수 있음

      • 메모리와 CPU가 최소 40 ~ 200 cycle 필요

    • Waiting vs Blocked

      • waiting : scheduler가 부르면 바로 실행 가능

      • blocked : 바로 실행 불가

    • pre-emptive scheduling

      • 선점형 스케줄링

      • 모든 프로세스에게 CPU 사용 시간을 동일하게 부여

      • 모든 OS에서 다 지원

      • Multitasking

      • Job scheduling(Task scheduling)

Thread

  • process와 thread 모두 실행의 흐름일 뿐이다.(instruction의 나열)

  • process는 무조건 하나 이상의 thread를 가진다.

  • Single Thread

    • 하나의 프로세스에서 하나의 스레드 실행
  • Concurrency Programming

    1. Multi - Processing

      • Inter Process Communication(IPC)를 통해 통신해야 함
    2. Multi - Thread

      • 메모리를 물리적으로 공유
    3. I/O bound한 작업을 할 때

      • Asynchonous(비동기) I/O
  • Multi - Threading의 약점

    1. GIL(Global Interpreter Lock)

      • 코어가 많아도 하나의 스레드 밖에 쓰지 못함
    2. Race Condition(경쟁 상태)

      • 프로세스들이 하나의 데이터를 동시에 요청할 때 원치 않은 결과가 나올 수 있음

      • 해결 방법 : Mutual Exclusion(상호 배제)

        • 한 프로세스가 점유한 자원을 다른 프로세스들이 접근할 수 없도록 함
  • Thread Pool

    • Thread를 여러개 만든 후에 Thread 작업이 끝나면 Thread가 사라지지 않고 작업하지 않을 때는 잠시 쉼
  • 다음 키워드들을 찾아보자.

    • Critical Condition

    • Critical Section

    • Mutex

    • Semaphore

OOP 정리

  1. Encapsulation(캡슐화)

    • 얼마만큼 관련이 있는가?

    • “관련있는” = single responsibility = 변수(데이터) + 함수를 하나의 단위로 묶는 것

  2. Information Hiding(정보은닉)

    • 어떤 멤버와 메서드를 공개하고 비공개할 것인가?
  3. Polymorphism(다형성)

    • 상속(Inheritance)

    • Method overriding

  • Relation of classes

    1. IS-A

      • 상속으로 구현
    2. HAS-A

      1. Composition = Same life cycle, Strongly couple

      2. Aggregation = Different life cycle, Weak couple

      • Code reusability만을 위한 거라면 composition을 사용하는 것이 좋다.
  • SOLID

  1. Single responsibility principle

    • 클래스가 바뀌는 이유는 단 하나의 기능 때문이어야 한다.
  2. Open-Closed principle

    • 확장에 대해서는 열려있지만, modification은 닫혀있어야 한다.
  3. Liskov substitution principle

    • 인터페이스 명세

    • 부모 클래스를 상속받는 자식클래스로 만든 객체에 부모 클래스 객체를 넣어도 잘 수행되어야 한다.

  4. Interface segregation principle

    • 꼭 필요한 메서드들만 이용할 수 있게 함
  5. Dependency inversion principle

    • 변화하는 부분 -> 추상화
Share