안녕하세요, SSAFYcial 신산하입니다 : )
5월 기획기사의 주제는 운영체제편으로 가져왔습니다!
프로그래밍에 입문하고 심심치 않게 들었던 스레드,
도대체 정체가 무엇일까요?
지금부터 아주 간단하게 설명드리겠습니다 : )
1. 쓰레드(Thread)란?
쓰레드(Thread)는 프로세스 내 작업의 흐름입니다. 여기서 프로세스는 컴퓨터에서 실행되고 있는 프로그램이라고 보시면 됩니다. 쓰레드가 프로세스 내에서 실제 작업을 수행하는 주체입니다.
각각의 프로세스는 적어도 1개의 메인 쓰레드를 가지고 있습니다. 1개의 쓰레드를 싱글 쓰레드(Single Thread)라고 합니다.
그러나 싱글 쓰레드에서 다양한 일을 수행하다보면 일의 처리가 너무 느려질 때가 있습니다.
이를 해결하기 위해 멀티 쓰레드(Multi Thread)를 사용합니다. 즉, 2개 이상의 쓰레드를 사용하는 것입니다.
컴퓨터에서 실행되고 있는 하나의 프로그램(Process)에서 2개 이상의 쓰레드를 사용하면 프로그램에 구현되어 있는 여러 작업이 동시에 수행될 수 있습니다. 쓰레드를 1개 추가 생성하면, Main Thread + Work Thread가 생기는 것이죠.
멀티쓰레드를 이용함으로써 병렬성과 동시성을 높일 수 있는 것입니다.
2. 자바에서도 멀티 쓰레드 사용이 가능하다고?
자바에서도 쓰레드 생성이 가능합니다. 무려 2가지 방법이 있습니다!
1) Thread 클래스 상속
class ThreadWithClass extends Thread {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(getName()); // 현재 실행 중인 스레드의 이름을 반환함.
try {
Thread.sleep(10); // 0.01초간 스레드를 멈춤.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
스레드를 상속해서 새로운 스레드를 정의합니다. 그 후 run 메소드를 재정의해줍니다.
2) Runnable 구현
class ThreadWithRunnable implements Runnable {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()); // 현재 실행 중인 스레드의 이름을 반환함.
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Runnable의 run 메서드를 구현합니다.
두 방식의 차이는 상속해서 재정의를 하냐, 인터페이스를 구현하냐의 차이도 있지만, 메인함수에서 사용하는 법과 생성되는 방식에도 차이가 있습니다.
3) 두 방식의 차이점
public class Thread01 {
public static void main(String[] args){
ThreadWithClass thread1 = new ThreadWithClass(); // Thread 클래스를 상속받는 방법
Thread thread2 = new Thread(new ThreadWithRunnable()); // Runnable 인터페이스를 구현하는 방법
thread1.start(); // 스레드의 실행
thread2.start(); // 스레드의 실행
}
}
클래스를 상속받은 경우 클래스를 재구현한 형태이기 때문에 그대로 new 스레드클래스()로 생성하면 됩니다.
하지만 인터페이스를 구현한 경우 Thread 클래스 안에 새롭게 구현한 스레드를 넣어줘야 합니다.
일반적으로 자바는 한 클래스당 하나의 클래스를 상속받을 수 있습니다. 때문에 Thread 클래스를 상속받으면 다른 클래스를 상속받을 수 없기 때문에 기본적으로 Runnable 인터페이스를 구현하는 방식을 채택합니다. 인터페이스는 자격증과도 같기 때문에 여러 개를 구현할 수 있기 때문입니다.
3. 파이썬에서도 멀티 쓰레드 사용이 가능하다고?
파이썬에서는 import threading을 이용해 가능합니다.
threading.Thread(targer=runServer, arg=(클라이언트 소켓 주소))로 새로운 스레드를 생성하고, start() 함수를 이용해 실행이 가능합니다.
4. 공유자원 문제
예를 들어 인터넷 뱅킹 시스템을 생각해보시면 됩니다. 각 스레드에서 각 고객이 요청하는 일을 수행할 겁니다. 그럴 때 각 스레드는 스레드 별로 다른 고객 정보를 가지고 있는 것이 아닙니다. 공유되는 변수 등 공유 자원이 있어서 그 자원을 일을 수행하면서 건들이게 됩니다.
즉, 공유자원(shared resources)는 시스템 안에서 각 프로세스, 스레드가 함께 접근할 수 있는 모니터, 프린터, 메모리, 파일, 데이터 등의 자원이나 변수 등을 의미합니다.
그런데 스레드에는 임계영역이 존재합니다. 임계영역이라는 것은 둘 이상의 프로세스, 스레드가 공유 자원에 접근할 때 순서 등의 이유로 결과가 달라지는 코드 영역을 의미합니다. 임계영역을 해결하기 위한 방법으로는 뮤텍스, 세마포어, 모니터 등 다양하지만, 특히 이 세가지의 방법에 토대가 되는 메커니즘은 잠금(lock)입니다.
즉, 파란색 과정 중 신산하의 금액을 건드는 작업이 있는데, 누가 금액을 건들고 있으면 다른 작업은 접근을 lock 시키는 방안입니다. 큐 안에서 자신의 차례가 올 때까지 기다리는 모습을 상상하면 될 것 같습니다.
// 1. 서버는 클라이언트들의 정보를 저장하기 위해 해시맵을 가지고 있다.
HashMap clients;
multiAccounts_Server(){
clients = new HashMap();
//2. 어떤 스레드가 해시맵을 사용하고 있는 도중에는 다른 클래스는 사용 못하도록 합니다. (동기화)
Collections.synchronizedMap(clients);
}
예를 들어 자바의 경우 Collections.syncronizedMap을 이용해 클라이언트의 정보를 저장하고 있는 해시맵에 특정 스레드가 접근하고 있다면 다른 스레드는 사용 못하도록 방지하는 방법이 있습니다. 동기화시키는 겁니다.
lock = threading.lock()
파이썬의 경우 lock 함수를 이용하여 어떤 스레드가 데이터에 접근하고 있을 때 다른 스레드가 데이터에 접근하는 것을 막을 수 있습니다. 이도 동기화시키는 겁니다.
5. 교착 상태 (Dead lock)
lock을 시키는 방안까지는 좋은데, 이런 상황이 발생할 수도 있습니다. 예를 들어 2개 이상의 프로세스들이 서로가 가진 자원을 기다리며 무한 대기하고 있는 상황입니다.
교착 상태의 원인은 크게 4가지가 있습니다.
- 상호 배제 : 한 프로세스가 자원을 독점하고 있어 다른 프로세스가 못쓰는 경우 (화장실로 생각하면 끔찍)
- 점유 대기 : 특정 프로세스가 점유한 자원을 다른 프로세스가 요청하는 상태
- 비선점 : 다른 프로세스의 자원을 강제적으로 가져올 수 없음
- 환형 대기 : 프로세스 A는 프로세스 B의 자원을 요구하고, 프로세스 B는 프로세스 A의 자원 요구 (니꺼 내놔~~)
그렇다면 어떻게 해결할 수 있을까요?
은행원 알고리즘 등 다양한 방법이 있지만, 아주 간단한 해결 방안을 하나 소개시켜드리겠습니다.
현대 운영체제의 경우 교착상태에 있는 사용자의 작업을 종료시키는 방안을 채택했습니다.
왜냐하면, 교착 상태는 아주 드물게 일어나고, 이를 처리하는 비용이 더 커서 오히려 교착 상태를 해결하는 게 손해라는 것이죠.
오늘은 운영체제 중 Thread에 관련하여 정보를 작성해보았습니다.
여러분의 면접에 많은 도움이 되었으면 좋겠습니다 : )
이제 곧 학기의 마지막이 다가옵니다.
모두 각자의 위치에서 최선을 다해 좋은 결과를 이루기를 소원하겠습니다!
이번 달도 고생 많으셨습니다.
출처
1. 코딩의 시작, TCP School
http://www.tcpschool.com/java/java_thread_concept
2. 면접을 위한 CS 전공지식 노트
'대외활동 > SSAFYicial' 카테고리의 다른 글
[기업탐방] "꿈의 기업 삼성전자", 제가 생각하던 회사의 기준이 달라졌어요! (1) | 2023.06.21 |
---|---|
[TMI] 대전을 고민하시는 예비 SSAFY인들을 위한 1학기 리얼 후기 (with 타지생활) (12) | 2023.05.13 |
[CS 정리는 내가 할게, 면접은 누가볼래? - Github편] Github 어디까지 해봤니? 소스트리 설정부터 브랜치 관리까지 총정리! (5) | 2023.04.18 |
[CS 정리는 내가 할게, 면접은 누가볼래? - 데이터베이스편] 실제 프로젝트를 통해 알아보는 데이터베이스 기초! ENTITY TITI FRAGILE X 2~ (2) | 2023.03.12 |
[TMI] 내가 퇴사하고, SSAFY한 이유, "난 아직 젊다!" (6) | 2023.03.11 |