OS에서 어떤 실행 프로그램이 실행된다는 것은 CPU, 메모리, SSD와 같은 컴퓨터 자원을 사용한다
OS가 프로그램들이 실행될 수 있도록 부여하는 공간을 프로세스 라고 한다.
프로세스에는 응용 프로그램이 있다. OS 입장에서 프로세스에 있는 객체를 Thread라고 한다.
Thread
- 프로그램이라고 부르는 것은 OS위에서 동작한다
- 프로그램이 메모리에 올라가서 실행 중인 것을 프로세스라고 부른다
- 프로세스의 실행 단위를 스레드 라고 한다.
- 프로세스는 최소 하나 이상의 스레드를 가지며 경우에 따라 여러 스레드를 가질 수 있다(멀티스레드)
우리가 윈도우를 사용할 때 메신저도 사용하고 게임도 하고 문서작성도 하고 인터넷도 사용한다
윈도우는 동시에 실행되는 여러 프로그램들을 잘 관리해야하는데 이런 작업을 스케줄링이라고 한다.
운영체제는 스케쥴링의 단위로 스레드를 사용한다
threading 모듈 사용
파이썬 기본 모듈로 thread, threading 모듈이 있으며 PyQt 의 QThread도 있다
#threading 모듈 사용
import threading
import time
class Worker(threading.Thread):
def __init__(self, name):
super().__init__()
self.name = name # thread 이름 지정
def run(self):
print("sub thread start ", threading.currentThread().getName())
time.sleep(3)
print("sub thread end ", threading.currentThread().getName())
print("main thread start")
for i in range(5):
name = "thread {}".format(i)
t = Worker(name) # sub thread 생성
t.start() # sub thread의 run 메서드를 호출
print("main thread end")
main thread start
sub thread start thread 0
sub thread start thread 1
sub thread start thread 2
sub thread start thread 3
sub thread start thread 4
main thread end
sub thread end thread 0
sub thread end thread 1
sub thread end sub thread end thread 2
thread 4
sub thread end thread 3
메인 스레드가 5개의 서브 스레드를 생성하고 start 메소드를 호출하여 Worker 클래스의 run() 메소드 호출
서브 스레드들은 0,1,2,3,4 순으로 실행됐지만 종료 순서는 조금 다르다
데몬 스레드
데몬(daemon) 스레드는 메인 스레드가 종료될 때 자신의 실행 상태와 상관없이 종료되는 서브 스레드 의미
threading 모듈을 사용해서 메인 스레드가 서브 스레드를 생성하는 경우 메인 스레드는 서브 스레드가 모두 종료될 때까지 기다렸다가 종료하게 된다. 하지만 실제 프로그래밍을 하다보면 경우에 따라 메인 스레드가 종료되면 모두 서브스레드가 동작 여부에 상관없이 종료되어야 하는 경우가 많다. 이때 서브 스레드 들은 데몬 스레드로 만들어져야 한다.
#데몬 스레드
import threading
import time
class Worker(threading.Thread):
def __init__(self, name):
super().__init__()
self.name = name # thread 이름 지정
def run(self):
print("sub thread start ", threading.currentThread().getName())
time.sleep(3)
print("sub thread end ", threading.currentThread().getName())
print("main thread start")
for i in range(5):
name = "thread {}".format(i)
t = Worker(name) # sub thread 생성
t.daemon = True
t.start() # sub thread의 run 메서드를 호출
print("main thread end")
main thread start
sub thread start thread 0
sub thread start thread 1
sub thread start thread 2
sub thread start thread 3
sub thread start thread 4
main thread end
실행 결과를 확인해보면 메인 스레드가 종료되면서 time.sleep(3)에 의해 대기 상태에 있던 서브 스레드들은 끝나기 전에 모두 종료된 것을 확인할 수 있다.
Fork & Join
Fork : 메인 스레드가 서브 스레드를 생성 하는 것
Join : 모든 스레드가 작업을 마칠 때까지 기다리는 것, 보통 데이터를 여러 스레드를 통해서 병렬로 처리한 후 그 값들을 다시 모아서 순차적으로 처리해야할 필요가 있을 때 분할한 데이터가 모든 스레드에서 처리될 때까지 기다렸다가 메인 스레드가 다시 추후 작업을 하는 경우에 사용한다
import threading
import time
class Worker(threading.Thread):
def __init__(self, name):
super().__init__()
self.name = name # thread 이름 지정
def run(self):
print("sub thread start ", threading.currentThread().getName())
time.sleep(5)
print("sub thread end ", threading.currentThread().getName())
print("main thread start")
t1 = Worker("1") # sub thread 생성
t1.start() # sub thread의 run 메서드를 호출
t2 = Worker("2") # sub thread 생성
t2.start() # sub thread의 run 메서드를 호출
t1.join()
t2.join()
print("main thread post job")
print("main thread end")
main thread start
sub thread start 1
sub thread start 2
sub thread end 2
sub thread end 1
main thread post job
main thread end
결과를 보면 t1, t2 스레드가 종료된 후 'main thread post job'이 출력된 것을 확인할 수 있다
참고로 앞의 예에서는 메인스레드가 모든 실행을 완료한 후 서브스레드가 종료될 때까지 기다렸지만 이 예제에서는 join( ) 메서드가 호출되는 지점에서 기다린다는 차이가 있다
'Backend > Python' 카테고리의 다른 글
Web Framework Django 시작하기(1) - 프로젝트 생성 (0) | 2022.01.08 |
---|---|
Python Multithread vs Multiprocessing (0) | 2021.12.29 |
Python Flask 웹 페이지 제작(3) - Form (0) | 2021.12.21 |
Python Flask 웹 페이지 제작(2) - Jinja2 템플릿 (2) | 2021.12.21 |
Python Flask 웹 페이지 제작(1) - 구조, Route (0) | 2021.12.21 |