F-LAB JAVA · 4주차 · Phase 1 · 동시성의 기초
이 Unit을 끝내면 다음을 답할 수 있어야 한다.
프로세스 (Process) 는 실행 중인 프로그램으로 독립적인 메모리 공간을 가지며, 스레드 (Thread) 는 프로세스 안에서 코드를 한 줄씩 실행하는 흐름이다.
하나의 프로세스는 최소 1개 이상의 스레드 를 반드시 포함 (메인 스레드).
프로세스의 메모리 중 코드/데이터/힙 (Heap) 은 모든 스레드가 공유 하고, 스택 (Stack) 은 스레드마다 개별 할당된다.
스택이 개별인 이유는 각 스레드가 독립적인 실행 흐름 (메서드 호출, 지역 변수) 을 가져야 하기 때문이고, 힙이 공유인 이유는 스레드들이 협력하며 데이터를 주고받기 위함.
바로 이 공유 메모리 (힙) 때문에 동시성 문제 (데이터 불일치) 가 발생하며, 이것이 4주차의 핵심 주제다.
프로세스 = 독립된 회사 (건물)
- 각 회사는 독립된 사무실 공간 (메모리)
- 다른 회사의 자료에 직접 접근 X
- 회사 간 소통은 별도 절차 (IPC)
스레드 = 회사 안의 직원들
- 같은 회사 자료실 (힙) 공유
- 각자 개인 책상 (스택)
- 자료실에서 협력
- 같은 자료 동시 수정 시 충돌 (동시성 문제)
공유 자료실 (힙):
- 직원들이 함께 사용
- 동시에 같은 문서 수정하면? → 충돌
- 규칙 (동기화) 필요
개인 책상 (스택):
- 각자 개인 작업
- 충돌 없음 (스레드 안전)
→ 프로세스 = 회사, 스레드 = 직원, 힙 = 공유 자료실, 스택 = 개인 책상.
1. 프로세스의 정의와 특징
2. 스레드의 정의와 특징
3. 프로세스의 메모리 구성
4. 스레드의 공유 vs 개별
5. 스택이 개별인 이유
6. 클래스/인스턴스 비유
7. PCB와 TCB
8. 멀티프로세스 vs 멀티스레드
9. 면접 + 자기 점검
프로세스 (Process):
실행 중인 프로그램.
디스크의 프로그램 파일이 메모리에 올라와
실행되고 있는 상태.
특징:
- 독립적인 메모리 공간
- OS 가 작업 단위로 관리
- 최소 1개 스레드 포함
프로그램 (Program):
- 디스크의 정적 파일
- 실행 코드 + 데이터
- 예: shipment.jar
프로세스 (Process):
- 실행 중인 프로그램
- 메모리에 로드됨
- 동적 (실행 상태)
- 예: java -jar shipment.jar 실행 중
비유:
- 프로그램 = 요리 레시피 (종이)
- 프로세스 = 실제 요리하는 중
프로세스의 독립적 메모리:
프로세스 A 프로세스 B
┌──────────┐ ┌──────────┐
│ 코드 │ │ 코드 │
│ 데이터 │ │ 데이터 │
│ 힙 │ │ 힙 │
│ 스택 │ │ 스택 │
└──────────┘ └──────────┘
서로 직접 접근 X
- A 가 B 의 메모리 못 봄
- OS 가 보호 (메모리 격리)
장점:
- 안정성 (한 프로세스 죽어도 다른 건 OK)
- 보안
단점:
- 통신 비용 (IPC 필요)
- 생성 비용 큼
IPC (Inter-Process Communication):
프로세스들이 데이터를 주고받는 방법.
종류:
- 파이프 (Pipe)
- 소켓 (Socket)
- 공유 메모리 (Shared Memory)
- 메시지 큐 (Message Queue)
- 시그널 (Signal)
특징:
- 별도 메커니즘 필요
- 스레드 간 통신보다 비용 ↑
프로세스 생성:
fork() (Unix):
- 부모 프로세스 복제
- 자식 프로세스 생성
비용:
- 메모리 공간 할당
- 자원 복사
- 큼
자바 프로세스:
- JVM 하나가 1 프로세스
- java -jar app.jar = 1 프로세스
// ILIC 서버는 1개 JVM 프로세스
// java -jar ilic.jar
// 외부 프로세스 실행 (드물게)
public class ExternalProcessExample {
public void runConverter(Path input, Path output) throws IOException, InterruptedException {
// 별도 프로세스 실행 (PDF 변환 등)
ProcessBuilder pb = new ProcessBuilder(
"wkhtmltopdf", input.toString(), output.toString());
Process process = pb.start(); // 새 프로세스
int exitCode = process.waitFor(); // 완료 대기
if (exitCode != 0) {
throw new IOException("Conversion failed");
}
}
}
// 하지만 대부분의 동시 처리는
// 같은 프로세스 안의 멀티스레드로
프로세스의 정의와 특징은?
답:
1. 정의:
프로그램 vs 프로세스:
독립성:
통신:
특징:
스레드 (Thread):
프로세스 안에서 코드를 한 줄씩 실행하는 흐름.
"실 (thread)" 이 코드를 위에서 아래로 꿰는 것.
특징:
- 프로세스의 자원 공유 (힙, 코드, 데이터)
- 자체 스택 보유
- 실행의 최소 단위
스레드 = 실행 흐름:
코드:
line 1: int x = 10;
line 2: process(x);
line 3: return x;
스레드:
- line 1 → line 2 → line 3 순차 실행
- "실" 이 코드를 꿰는 것
멀티스레드:
스레드 A: line 1 실행 중
스레드 B: line 5 실행 중
→ 같은 코드를 여러 흐름이 동시 진행
메인 스레드 (Main Thread):
프로세스 시작 시 자동 생성되는 첫 스레드.
자바:
public static void main(String[] args) {
// 이 코드는 메인 스레드에서 실행
}
특징:
- 모든 프로세스는 메인 스레드로 시작
- 추가 스레드는 메인에서 생성
- 메인 스레드 종료 ≠ 프로세스 종료 (다른 스레드 있으면)
스레드 생성 비용 (프로세스보다 적음):
프로세스 생성:
- 새 메모리 공간
- 자원 복사
- 큼
스레드 생성:
- 스택만 새로 (약 1MB)
- 힙, 코드 공유
- 상대적으로 적음
- 하지만 여전히 비용 있음 (Phase 7 에서 풀)
멀티스레드의 장점:
1. 자원 공유
- 힙, 코드 공유
- 메모리 효율
2. 통신 쉬움
- 공유 메모리로 직접
- IPC 불필요
3. 생성 비용 적음
- 프로세스보다
4. 컨텍스트 스위칭 빠름
- 같은 프로세스 내
- 메모리 공간 유지
단점:
- 동기화 문제 (공유 자원)
- 한 스레드 오류가 전체 영향
// 자바 스레드 생성
public class ShipmentThreadExample {
public void demonstrateThreads() {
// 메인 스레드에서 실행 중
System.out.println("Main: " + Thread.currentThread().getName());
// "Main: main"
// 새 스레드 생성
Thread worker = new Thread(() -> {
System.out.println("Worker: " + Thread.currentThread().getName());
processShipments();
});
worker.start(); // 새 흐름 시작
// 메인 스레드는 계속 진행
System.out.println("Main continues");
}
private void processShipments() {
// 별도 스레드에서 실행
}
// 현재 스레드 정보
public void printThreadInfo() {
Thread current = Thread.currentThread();
System.out.println("Name: " + current.getName());
System.out.println("ID: " + current.threadId());
System.out.println("State: " + current.getState());
System.out.println("Priority: " + current.getPriority());
}
}
스레드의 정의와 특징은?
답:
1. 정의:
메인 스레드:
장점:
단점:
본질:
프로세스 메모리 구성:
┌─────────────────────┐
│ 코드 섹션 (Code) │ ← 실행 코드 (읽기 전용)
├─────────────────────┤
│ 데이터 섹션 (Data) │ ← 전역/static 변수
├─────────────────────┤
│ 힙 (Heap) │ ← 동적 할당 (new)
│ ↓ │
│ │
│ ↑ │
│ 스택 (Stack) │ ← 메서드 호출, 지역 변수
└─────────────────────┘
코드 섹션 (Code/Text Section):
- 실행할 프로그램의 기계어 코드
- 읽기 전용 (수정 불가)
- 모든 스레드 공유
자바:
- Method Area 의 일부
- 클래스의 바이트코드
- JIT 컴파일된 네이티브 코드
데이터 섹션 (Data Section):
- 전역 변수
- static 변수
- 모든 스레드 공유
자바:
- Method Area (Metaspace)
- static 필드
- 상수 풀
멀티스레드:
- 공유됨 → 동기화 필요
힙 (Heap):
- 동적 메모리 할당
- new 로 생성한 객체
- 모든 스레드 공유
자바:
- 모든 객체 (인스턴스)
- 인스턴스 변수
- 배열
멀티스레드:
- 공유됨 → 동기화 필요 (★ 핵심)
- GC 대상
스택 (Stack):
- 메서드 호출 정보 (스택 프레임)
- 지역 변수
- 매개변수
- 리턴 주소
- 스레드마다 개별 ★
자바:
- 스레드 1개 = 스택 1개
- 메서드 호출마다 스택 프레임
- 메서드 종료 시 프레임 제거
멀티스레드:
- 개별 → 동기화 불필요 (스레드 안전)
프로세스 메모리 (3 스레드):
┌────────────────────────────────┐
│ 코드 섹션 (공유) │
├────────────────────────────────┤
│ 데이터 섹션 (공유, static) │
├────────────────────────────────┤
│ 힙 (공유, 객체들) │ ★ 동기화 필요
│ Shipment, Company, List... │
├────────────────────────────────┤
│ 스택1 │ 스택2 │ 스택3 │ ★ 개별 (스레드 안전)
│ (스레드A)│ (스레드B)│ (스레드C) │
└────────────────────────────────┘
public class ShipmentService {
// 데이터 섹션 (static, 공유)
private static final BigDecimal FUEL_RATE = BigDecimal.valueOf(0.15);
private static int totalProcessed = 0; // 공유 → 동기화 필요
// 힙 (인스턴스, 공유)
private final ShipmentRepository repository; // 객체 참조
private List<Shipment> cache = new ArrayList<>(); // 공유 → 위험
public Shipment process(Long id) {
// 스택 (지역 변수, 스레드별 — 안전)
Shipment shipment = repository.findById(id); // 지역 변수 (스택)
BigDecimal freight = calculate(shipment); // 지역 변수 (스택)
// 객체 자체는 힙에 (shipment 가 가리키는 것)
// shipment 참조는 스택에
return shipment;
}
private BigDecimal calculate(Shipment s) {
BigDecimal weight = s.getWeight(); // 지역 (스택)
return weight.multiply(FUEL_RATE); // FUEL_RATE 는 공유 (읽기만, 안전)
}
}
프로세스의 메모리 구성은?
답:
1. 4가지 영역:
공유 (스레드 간):
개별 (스레드별):
동기화 필요:
스레드가 공유하는 것:
1. 코드 섹션
- 같은 코드 실행
2. 데이터 섹션
- static 변수
- 전역 변수
3. 힙
- 모든 객체
- 인스턴스 변수
→ 협력의 기반
→ 동시성 문제의 근원
스레드가 개별로 갖는 것:
1. 스택
- 메서드 호출 정보
- 지역 변수
- 매개변수
2. PC (Program Counter)
- 다음 실행 명령 주소
3. 레지스터
- CPU 레지스터 상태
→ 독립적 실행 흐름
→ 스레드 안전
공유의 장점:
- 협력 (데이터 주고받기)
- 메모리 효율
- 빠른 통신
공유의 단점:
- 동시성 문제
- 데이터 불일치
- 동기화 필요
핵심:
- "스레드 안전한가?"
- = "공유되는가?"
- 공유되면 동기화 고려
변수 종류와 스레드 안전성:
지역 변수 (스택):
- 스레드별 개별
- 스레드 안전 ✓
인스턴스 변수 (힙):
- 객체 공유 시 공유
- 동기화 필요 (조건부)
static 변수 (데이터):
- 항상 공유
- 동기화 필요
매개변수 (스택):
- 스레드별
- 안전 (단, 참조 객체는 공유 가능)
// 지역 변수지만 위험한 경우
public void process() {
// 지역 변수 (스택) — 안전?
List<Shipment> list = sharedList; // ★ 공유 객체 참조!
list.add(shipment); // 위험! (sharedList 가 공유)
// list 참조 자체는 스택 (안전)
// 하지만 list 가 가리키는 객체는 공유 (힙)
}
// 진짜 안전한 경우
public void processSafe() {
List<Shipment> list = new ArrayList<>(); // 새 객체 (지역)
list.add(shipment); // 안전 (이 스레드만 접근)
}
스레드 A 와 B 의 메모리:
힙 (공유):
┌────────────────────┐
│ Shipment 객체 │ ← A, B 모두 접근 가능
│ List 객체 │ ← 동시 수정 위험
└────────────────────┘
↑ ↑
│ │
스택 A 스택 B
┌──────┐ ┌──────┐
│참조 →│ │참조 →│ ← 같은 객체 가리킬 수 있음
│지역x │ │지역y │ ← 각자 개별 (안전)
└──────┘ └──────┘
public class ShipmentCounter {
// ❌ 공유 변수 (위험)
private int count = 0; // 인스턴스 변수 (힙, 공유)
public void increment() {
count++; // 여러 스레드 동시 → 데이터 손실
}
// ✓ 동기화
public synchronized void incrementSafe() {
count++;
}
// ✓ Atomic (Phase 후반)
private final AtomicInteger atomicCount = new AtomicInteger();
public void incrementAtomic() {
atomicCount.incrementAndGet();
}
// ✓ 지역 변수 (안전)
public int calculate(List<Shipment> shipments) {
int localSum = 0; // 지역 변수 (스택, 안전)
for (Shipment s : shipments) {
localSum += s.getQuantity();
}
return localSum;
// localSum 은 이 스레드만 접근
}
}
스레드의 공유 vs 개별은?
답:
1. 공유:
개별:
핵심 원칙:
함정:
질문:
왜 스레드들이 힙은 공유하고
스택은 따로 갖는가?
답:
- 스택: 독립적 실행 흐름 필요
- 힙: 협력 (데이터 공유) 필요
스택 = 실행 흐름:
각 스레드는 독립적으로 코드 실행:
- 자기만의 메서드 호출 순서
- 자기만의 지역 변수
- 자기만의 실행 위치 (PC)
만약 스택을 공유한다면?
- 스레드 A 의 메서드 호출과
- 스레드 B 의 메서드 호출이
- 같은 스택에 섞임
- → 완전히 망가짐
따라서:
- 스택은 반드시 개별
- 독립적 실행 보장
스레드 A 의 스택:
┌────────────────┐
│ calculate() │ ← 현재 실행 중
│ - weight │
├────────────────┤
│ process() │
│ - shipment │
├────────────────┤
│ main() │
└────────────────┘
스레드 B 의 스택 (완전 독립):
┌────────────────┐
│ validate() │ ← 다른 메서드
│ - result │
├────────────────┤
│ handleRequest()│
└────────────────┘
각자 독립적 호출 스택
서로 영향 X
힙 = 협력의 공간:
스레드들이 협력하려면 데이터 공유 필요:
- 생산자가 만든 데이터를
- 소비자가 사용
- 공유 큐 (힙)
만약 힙도 개별이라면?
- 데이터 공유 불가
- IPC 같은 비싼 통신 필요
- 멀티스레드의 장점 상실
따라서:
- 힙은 공유
- 협력 가능
- 단, 동시성 문제 (트레이드오프)
공유 vs 개별의 트레이드오프:
스택 개별:
+ 독립 실행 흐름
+ 스레드 안전
- 공유 불가 (지역 변수)
힙 공유:
+ 협력 가능
+ 메모리 효율
- 동시성 문제
설계 의도:
- 실행 흐름은 독립 (스택)
- 데이터는 공유 (힙)
- 균형
// 스택 크기 설정
// -Xss 옵션 (기본 약 512KB ~ 1MB)
// java -Xss1m App
// 스택 오버플로우
public void recursive(int n) {
recursive(n + 1); // 무한 재귀
// StackOverflowError
// 스택 크기 초과
}
// 스레드마다 스택
// 스레드 1만 개 = 약 1만 MB (1MB씩)
// → 메모리 부족 가능
// → 스레드 풀 (Phase 7)
public class StackHeapExample {
// 힙 — 공유 (동기화 필요)
private final Map<Long, Shipment> sharedCache = new ConcurrentHashMap<>();
public void process(Long id) {
// 스택 — 이 스레드의 독립 실행
Shipment local = sharedCache.get(id); // local 참조는 스택
// local 이 가리키는 객체는 힙 (공유)
// 지역 변수 (스택, 안전)
BigDecimal weight = local.getWeight();
boolean isHeavy = weight.compareTo(BigDecimal.valueOf(1000)) > 0;
// 다른 스레드의 스택과 완전 독립
// weight, isHeavy 는 이 스레드만
if (isHeavy) {
handleHeavy(local); // 새 스택 프레임
}
}
private void handleHeavy(Shipment s) {
// 새 스택 프레임 (이 스레드)
String message = "Heavy: " + s.getBlNo(); // 지역
log.info(message);
}
}
스택이 개별인 이유는?
답:
1. 스택 = 실행 흐름:
힙 = 협력 공간:
트레이드오프:
설계 의도:
프로세스 ↔ 인스턴스
스레드 ↔ ? (다양한 관점)
여러 비유가 있지만 가장 흔한:
프로세스 = 인스턴스 (객체)
- 독립된 상태 (메모리)
- 각자 자기 데이터
스레드 = 메서드 실행
- 인스턴스 안에서 동작
- 같은 인스턴스 데이터 접근
프로세스 = 회사:
- 독립된 건물 (메모리)
- 다른 회사와 격리
- 회사 간 소통은 절차 (IPC)
스레드 = 직원:
- 같은 회사 자료실 (힙) 공유
- 각자 책상 (스택)
- 직원 간 소통 쉬움 (공유)
공유 자료실 (힙):
- 동시 수정 충돌 (동시성)
- 규칙 필요 (동기화)
주방 비유:
프로세스 = 주방 (독립 공간)
스레드 = 요리사 (같은 주방 도구 공유)
도구 (힙) = 공유, 충돌 가능
손 (스택) = 개별
도로 비유:
프로세스 = 도로
스레드 = 차선
여러 차선이 같은 도로에서
책 비유:
프로세스 = 책 (전체)
스레드 = 책갈피 (읽는 위치)
여러 책갈피가 같은 책을
비유의 주의:
비유는 이해를 돕지만 완벽하지 않음.
예:
- 회사-직원: IPC 부분 부정확
- 클래스-인스턴스: 1:N 관계 다름
핵심은:
- 프로세스 = 독립 메모리
- 스레드 = 공유 + 개별 스택
- 정확한 메모리 모델 이해
// ILIC 서버 = 1개 프로세스 (회사)
// 여러 요청 처리 스레드 (직원)
@Service
public class ShipmentService {
// 공유 자료실 (힙) — 모든 스레드 접근
private final ShipmentRepository repository;
private final Map<Long, Shipment> cache = new ConcurrentHashMap<>();
// 여러 스레드 (직원) 가 동시 호출
public Shipment process(Long id) {
// 각 스레드는 자기 책상 (스택)
// 지역 변수는 독립
Shipment local = cache.computeIfAbsent(id, repository::findById);
// cache 는 공유 (자료실)
// local 참조는 스택 (책상)
return local;
}
}
프로세스/스레드를 비유하면?
답:
1. 회사-직원 비유:
클래스-인스턴스:
비유의 한계:
핵심:
PCB (Process Control Block):
OS 가 프로세스를 관리하기 위한 정보 구조.
포함 정보:
- 프로세스 ID (PID)
- 프로세스 상태
- PC (Program Counter)
- 레지스터 값
- 메모리 정보
- 열린 파일 목록
- 우선순위
...
TCB (Thread Control Block):
OS 가 스레드를 관리하기 위한 정보 구조.
포함 정보:
- 스레드 ID
- 스레드 상태
- PC
- 레지스터 값
- 스택 포인터
...
PCB 와 차이:
- TCB 는 더 가벼움
- 스레드는 프로세스 자원 공유
- PCB 의 일부 정보 공유
컨텍스트 스위칭 시:
프로세스 전환 (PCB):
- 현재 PCB 에 상태 저장
- 다음 PCB 에서 복원
- 메모리 공간 전환 (TLB 플러시)
- 비용 큼
스레드 전환 (TCB):
- TCB 에 상태 저장/복원
- 같은 프로세스면 메모리 유지
- 비용 적음
핵심:
- 스레드 전환 < 프로세스 전환
// 자바 Thread 객체는 TCB 추상화
Thread t = new Thread(task);
t.threadId(); // 스레드 ID
t.getState(); // 상태
t.getName(); // 이름
t.getPriority(); // 우선순위
// 실제 OS TCB 와 매핑 (1:1 모델)
// Virtual Thread 는 다름 (M:N)
// 스레드별 독립 데이터 (TCB 관련 개념)
public class ShipmentContext {
private static final ThreadLocal<String> currentUser = new ThreadLocal<>();
public static void setUser(String user) {
currentUser.set(user); // 이 스레드만의 값
}
public static String getUser() {
return currentUser.get(); // 이 스레드의 값
}
public static void clear() {
currentUser.remove(); // ★ 메모리 누수 방지
}
}
// 각 스레드가 독립적 값
// 스택과 유사하게 스레드별 격리
// 단, 메모리 누수 주의 (remove 필수)
// 요청별 컨텍스트 (스레드 로컬)
@Component
public class RequestContext {
private static final ThreadLocal<RequestInfo> context = new ThreadLocal<>();
public void setCurrentRequest(RequestInfo info) {
context.set(info); // 현재 스레드 (요청)
}
public RequestInfo getCurrentRequest() {
return context.get();
}
public void clear() {
context.remove(); // 요청 끝나면 정리
}
record RequestInfo(String userId, String requestId, Instant startTime) {}
}
// 주의:
// - 스레드 풀에서 스레드 재사용
// - 이전 요청의 값이 남을 수 있음
// - 반드시 clear (remove)
PCB와 TCB는?
답:
1. PCB:
TCB:
컨텍스트 스위칭:
자바:
| 항목 | 멀티프로세스 | 멀티스레드 |
|---|---|---|
| 메모리 | 독립 | 공유 (힙) |
| 통신 | IPC (느림) | 공유 메모리 (빠름) |
| 생성 비용 | 큼 | 적음 |
| 컨텍스트 스위칭 | 비쌈 | 쌈 |
| 안정성 | 높음 (격리) | 낮음 (전파) |
| 동기화 | 덜 필요 | 필요 |
멀티프로세스:
장점:
- 안정성 (한 프로세스 죽어도 다른 건 OK)
- 보안 (격리)
- 독립성
단점:
- 통신 비용 (IPC)
- 생성 비용 큼
- 메모리 많이
예:
- Chrome 브라우저 (탭마다 프로세스)
- 한 탭 죽어도 다른 탭 OK
멀티스레드:
장점:
- 통신 쉬움 (공유 메모리)
- 생성 비용 적음
- 메모리 효율
단점:
- 동기화 문제
- 한 스레드 오류 전체 영향
- 디버깅 어려움
예:
- 웹 서버 (요청마다 스레드)
- 게임 (렌더링, 물리, 입력 스레드)
Chrome 브라우저의 멀티프로세스:
- 각 탭 = 별도 프로세스
- 한 탭이 크래시 → 그 탭만
- 다른 탭 영향 X
이유:
- 안정성 우선
- 보안 (탭 간 격리)
- 메모리 비용 감수
대조:
- 옛 브라우저 (멀티스레드)
- 한 탭 멈추면 전체 멈춤
멀티프로세스 선택:
✓ 안정성 최우선
✓ 격리 필요
✓ 독립 실행
멀티스레드 선택:
✓ 빠른 통신
✓ 자원 공유
✓ 효율 우선
대부분의 서버 앱:
- 멀티스레드 (효율)
- + 프로세스 격리는 컨테이너로 (Docker)
// ILIC 는 멀티스레드 (단일 JVM)
// 톰캣 스레드 풀로 요청 처리
// server.tomcat.threads.max=200
// 200 스레드가 요청 처리 (멀티스레드)
// 격리는 컨테이너 레벨
// - Docker 컨테이너마다 별도 JVM 프로세스
// - 한 컨테이너 죽어도 다른 건 OK
// - Kubernetes 가 관리
// 외부 프로세스는 드물게
@Service
public class DocumentConverter {
public Path convertToPdf(Path html) throws IOException, InterruptedException {
// 별도 프로세스 (격리)
Process process = new ProcessBuilder(
"wkhtmltopdf", html.toString(), "output.pdf")
.start();
process.waitFor();
// 변환 도구 크래시해도 메인 JVM 영향 X
return Path.of("output.pdf");
}
}
멀티프로세스 vs 멀티스레드는?
답:
1. 멀티프로세스:
멀티스레드:
선택:
현대:
| Q | 핵심 답변 |
|---|---|
| 프로세스? | 실행 중인 프로그램, 독립 메모리 |
| 스레드? | 프로세스 내 실행 흐름 |
| 프로그램 vs 프로세스? | 정적 파일 vs 실행 중 |
| 메모리 구성? | 코드/데이터/힙/스택 |
| 공유하는 것? | 코드, 데이터, 힙 |
| 개별인 것? | 스택 |
| 스택 개별 이유? | 독립 실행 흐름 |
| 힙 공유 이유? | 협력 (데이터 공유) |
| IPC? | 프로세스 간 통신 |
| PCB vs TCB? | 프로세스 vs 스레드 관리 정보 |
| 멀티프로세스 vs 멀티스레드? | 안정성 vs 효율 |
| 스레드 안전 근원? | 공유 여부 |
답:
답:
답:
답:
답:
1. 프로세스 vs 스레드
2. 메모리
3. 핵심 원칙
이번 Unit에서 프로세스/스레드의 메모리를 봤다면, 다음은 변수별 메모리 위치와 스레드 안전성.
🚀 Phase 1 — 동시성의 기초
✅ Unit 1.1 멀티태스킹 vs 멀티프로세싱
✅ Unit 1.2 프로세스와 스레드 ← 여기
⏭ Unit 1.3 변수 종류와 메모리 위치
⏭ Unit 1.4 스케줄링 큐와 컨텍스트 스위칭
🚀 Phase 1 — 동시성의 기초 (2/4 진행)
총: 2/35 Unit