쓰레드(thread) : 프로그램 내부의 흐름 또는 맥
보통 하나의 프로그램은 하나의 흐름이 있다.
int main(void)
{
int n = 0;
int m = 6;
printf("%d", n + m);
while (n < m)
{
n++;
}
printf("Bye");
}
위와 같은 일반적인 프로그램은 프로그램 시작 시부터 종료 때까지 하나의 흐름이 있다. 이를 single thread라고 한다.

Multithread : 한 프로그램에 2개 이상의 쓰레드가 존재하는 것. 따라서 프로세스 내부의 2개 이상의 쓰레드가 동시에 작업을 수행하는 것을 의미한다.
하지만 우리는 하나의 cpu 내부에서는 한번에 하나의 작업만 수행할 수 있다고 배웠었다. 그렇다면 이 다중쓰레드에서는 이 법칙이 위배되어 실제로 프로세스 내부에 2개 이상의 쓰레드가 동시에 실행되는 것일까?
정답은 아니다. concurrent와 simultaneous를 비교하면서 이유를 분석해 보자.
< Concurrent vs Simultaneous >
Multithread도 thread가 빠른 시간 간격으로 스위칭되어 동시에 수행하는 것처럼 보이는 것이다. cpu가 1개인 이상 여러 연산을 동시에 수행할 수 없다.
multithread의 예) web browser(화면 출력 쓰레드 + 데이터 읽어오는 쓰레드), word processor(화면 출력하는 쓰레드 + 키보드 입력받는 쓰레드 + 철자/문법 오류 확인 쓰레드) 등
Single Thread Program : 하나의 프로세스에 하나의 쓰레드(기본적으로 프로세스는 하나의 쓰레드를 가진 싱글 쓰레드이다.)
Multi Thread Program : 하나의 프로세스에 여러 개의 쓰레드.
Context Switching

지금까지의 context switching은 프로세스 단위였다면 이제는 thread 단위로 switching된다. 예를 들어 p1의 쓰레드 1이 실행되었다면 context switching될 때는 p1의 쓰레드 2가 실행된다.
현대의 컴퓨터는 거의 다중 쓰레드를 가진다.
쓰레드의 구조
쓰레드끼리 공유 : 프로세스의 메모리 공간을 공유(code, data), 프로세스의 자원 공유 (file, i/o)
쓰레드끼리 비공유 : 개별적인 pc(쓰레드마다 다음에 실행할 명령어 번지인 pc가 다름), sp, registers, stack(return address나 parameter가 stack에 저장되어 stack까지 공유하면 x)
지금까지 쓰레드를 배운 이유 ? ==> 프로세스 관리 부서의 중요 업무가 cpu 스케줄링과 쓰레드 혹은 프로세스의 동기화이기 때문. 이제 프로세스의 동기화 부분을 살펴보자.
1 ) Independent : 두 프로세스 간 아무 관계가 없는 독립적인 프로세스.
2 ) Cooperating : 시스템 안에서 하나의 프로세스가 다른 하나에게 영향을 주거나 받는 프로세스.
< cooperating process의 예시 >
Process Synchronization(프로세스 동기화) : shared data에 대한 동시 접근은 data inconsistency를 발생시킴. 이를 막기 위해 프로세스 동기화가 필요.
shared data에 대한 동시 접근으로 인한 data inconsistency 발생의 예 : 은행계좌 문제. 부모는 입금, 자녀는 출금하는 예제.
아래는 은행계좌 문제의 자바 코드이다.
class Test
{
public static void main(String[] args)
throws InterruptedException
{
BankAccount b = new BankAccount();
Parent p = new Parnet(b);
Child c = new Child(b);
p.start();
c.start();
p.join();
c.join();
System.out.println("\nbalance = " + b.getBalance());
}
}
class BankAccount
{
int balance;
void deposit(int amount)
{
balance = balance + amount;
}
void withdraw(int amoount)
{
balance = balance - amount;
}
int getBalancee()
{
return balance;
}
}
class Parent extends Thread
{
BankAccount b;
Parent(BankAccount b)
{
this.b = b;
}
public void run()
{
for (int i = 0; i < 1000; i++)
{
b.deposit(1000);
}
}
}
class Child extends Thread
{
BankAccount b;
Child(BankAccount b)
{
this.b = b;
}
public void run()
{
for (int i = 0; i < 1000; i++)
{
b.withdraw(1000);
}
}
}
자녀가 출금하는 쓰레드와 부모가 입금하는 쓰레드, 즉 멀티쓰레드로 프로그램 구성. 자녀와 부모가 같은 금액을 입금, 출금했는데 잔액이 잘못된 결과값이 나옴 ==> 임계구역 문제.