์์ ์ด์์ฒด์ ๋ฅผ ํ๋ฉด์ ์ฐ๋ ๋์ ๋ํด ํฌ์คํ ์ ํ์๋ค. ํ์ง๋ง, ๋ค์ ํ ๋ฒ ์๊ธฐํด๋ณด์.
์ค์ ๋ก ๋์์ ์ฒ๋ฆฌ๋ ์ ์๋ ํ๋ก์ธ์ค์ ๊ฐ์๋ CPU ์ฝ์ด์ ๊ฐ์์ ๋์ผํ๋ฐ, ์ด๋ณด๋ค ๋ง์ ๊ฐ์์ ํ๋ก์ธ์ค๊ฐ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ํจ๊ป ๋์์ ์ฒ๋ฆฌํ ์๋ ์๋ค.
๊ฐ ์ฝ์ด๋ค์ ์์ฃผ ์งง์ ์๊ฐ๋์ ์ฌ๋ฌ ํ๋ก์ธ์ค๋ฅผ ๋ฒ๊ฐ์๊ฐ๋ฉฐ ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ ํตํด ๋์์ ๋์ํ๋ ๊ฒ ์ฒ๋ผ ๋ณด์ด๊ฒ ํ ๋ฟ์ด๋ค.
์ด์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฉํฐ ์ค๋ ๋ฉ์ด๋ ๊ฒ์ด ์๋๋ฐ, ๋ฉํฐ ์ค๋ ๋๋ ํ๋์ ํ๋ก์ธ์ค ์์ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ์์ ์ ์ํํ๋ ๊ฒ์ ๋งํ๋ค. ์ฆ, ์ค๋ ๋๋ ํ๋์ ์์ ๋จ์๋ผ๊ณ ์๊ฐํ๋ค.
Thread๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ๋ํ์ ์ผ๋ก 2๊ฐ์ง ๋ฐฉ๋ฒ์ด ์๋ค.
class ThreadEx1_1 extends Thread {
public void run() {
// ๋ก์ง
}
}
class ThreadEx1_2 implements Runnable {
public void run() {
// ๋ก์ง
}
}
์ฒซ ๋ฒ์งธ๋ Thread๋ฅผ ์์๋ฐ๋ ๋ฐฉ๋ฒ์ด๋ค. Thread๋ ์ธ์ ๋ ์ง ์์์ด ๊ฐ๋ฅํ ์ํ์ด๊ณ , ์ด๋ฅผ ํ์ฉํ๊ธฐ ์ํด run์ด๋ผ๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค.
๋ ๋ฒ์งธ๋ Runnable์ implements๋ฅผ ํ๋ ๋ฐฉ๋ฒ์ด๋ค.
Runnable์ด๋, Thread๋ฅผ ์์๋ฐ๊ณ ์๋ Class์ด๋ค. ๋ฐ๋ผ์ ์ด๋ฅผ ์์ํจ์ผ๋ก์จ, ์ค๋ ๋๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ๋๋๋ค.
๋ณดํต ๋ ๋ฒ์งธ ๋ฐฉ๋ฒ์ ์ ํธํ๋ค.
Java์ extends์ ์์ ๋ฐฉ์์ ํ๋์ class๋ง ๊ฐ๋ฅํ ๋ฐ๋ฉด, implements๋ฅผ ํตํด ๋ค์ค ์์ ๊ธฐ๋ฅ์ ํตํด run์ ์ค๋ฒ ๋ผ์ด๋ฉ ํด์ผํ๋ค.
cf) static ๋ฉ์๋๋ ํด๋น ๋ฉ์๋๋ฅผ ํธ์ถํ ์ค๋ ๋ ์์ ์๊ฒ ์ ์ฉ๋๋ค๋ ์ ์ ์ ์ํด์ผํฉ๋๋ค.
์ค๋ ๋์ ์คํ์ run() ํธ์ถ์ด ์๋ start() ํธ์ถ๋ก ํด์ผํ๋ค.
Why?
์ฐ๋ฆฌ๋ ๋ถ๋ช run() ๋ฉ์๋๋ฅผ ์ ์ํ๋๋ฐ, ์ค์ ์ค๋ ๋ ์์ ์ ์ํค๋ ค๋ฉด start()๋ก ์์ ํด์ผ ํ๋ค๊ณ ํ๋ค.
run()์ผ๋ก ์์ ์ง์๋ฅผ ํ๋ฉด ์ค๋ ๋๊ฐ ์ผ์ ์ํ ๊น? ๊ทธ๋ ์ง ์๋ค. ๋ ๋ฉ์๋ ๋ชจ๋ ๊ฐ์ ์์ ์ ํ๋ค. ํ์ง๋ง run() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, ์ด๊ฑด ์ค๋ ๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์๋๋ค.
Java์๋ ์ฝ ์คํ(call stack)์ด ์๋ค. ์ด ์์ญ์ด ์ค์ง์ ์ธ ๋ช ๋ น์ด๋ค์ ๋ด๊ณ ์๋ ๋ฉ๋ชจ๋ฆฌ๋ก, ํ๋์ฉ ๊บผ๋ด์ ์คํ์ํค๋ ์ญํ ์ ํ๋ค.
๋ง์ฝ ๋์์ ๋ ๊ฐ์ง ์์ ์ ํ๋ค๋ฉด, ๋ ๊ฐ ์ด์์ ์ฝ ์คํ์ด ํ์ํ๊ฒ ๋๋ค.
์ค๋ ๋๋ฅผ ์ด์ฉํ๋ค๋ ๊ฑด, JVM์ด ๋ค์์ ์ฝ ์คํ์ ๋ฒ๊ฐ์๊ฐ๋ฉฐ ์ผ์ฒ๋ฆฌ๋ฅผ ํ๊ณ ์ฌ์ฉ์๋ ๋์์ ์์ ํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ฌ์ค๋ค.
์ฆ, run() ๋ฉ์๋๋ฅผ ์ด์ฉํ๋ค๋ ๊ฒ์ main()์ ์ฝ ์คํ ํ๋๋ง ์ด์ฉํ๋ ๊ฒ์ผ๋ก ์ค๋ ๋ ํ์ฉ์ด ์๋๋ค. (๊ทธ๋ฅ ์ค๋ ๋ ๊ฐ์ฒด์ run์ด๋ผ๋ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๊ฒ ๋ฟ์ด๊ฒ ๋๋ ๊ฒ..)
start() ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด, JVM์ ์์์ ์ค๋ ๋๋ฅผ ์ํ ์ฝ ์คํ์ ์๋ก ๋ง๋ค์ด์ฃผ๊ณ context switching์ ํตํด ์ค๋ ๋๋ต๊ฒ ๋์ํ๋๋ก ํด์ค๋ค.
์ฐ๋ฆฌ๋ ์๋ก์ด ์ฝ ์คํ์ ๋ง๋ค์ด ์์ ์ ํด์ผ ์ค๋ ๋ ์ผ์ฒ๋ฆฌ๊ฐ ๋๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ start() ๋ฉ์๋๋ฅผ ์จ์ผํ๋ ๊ฒ์ด๋ค!
start()๋ ์ค๋ ๋๊ฐ ์์
์ ์คํํ๋๋ฐ ํ์ํ ์ฝ ์คํ์ ์์ฑํ ๋ค์ run()์ ํธ์ถํด์ ๊ทธ ์คํ ์์ run()์ ์ ์ฅํ ์ ์๋๋ก ํด์ค๋ค.
์ค๋ ๋์ ์ํ๋ 5๊ฐ์ง๊ฐ ์๋ค
์ค๋ ๋๋ก ๊ตฌํํ๋ ๊ฒ์ด ์ด๋ ค์ด ์ด์ ๋ ๋ฐ๋ก ๋๊ธฐํ์ ์ค์ผ์ค๋ง ๋๋ฌธ์ด๋ค.
์ค์ผ์ค๋ง๊ณผ ๊ด๋ จ๋ ๋ฉ์๋๋ sleep(), join(), yield(), interrupt()์ ๊ฐ์ ๊ฒ๋ค์ด ์๋ค.
start() ์ดํ์ join()์ ํด์ฃผ๋ฉด main ์ค๋ ๋๊ฐ ๋ชจ๋ ์ข ๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ฃผ๋ ์ผ๋ ํด์ค๋ค.
๋ฉํฐ์ค๋ ๋๋ก ๊ตฌํ์ ํ๋ค๋ณด๋ฉด, ๋๊ธฐํ๋ ํ์์ ์ด๋ค.
๋๊ธฐํ๊ฐ ํ์ํ ์ด์ ๋, ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๊ฐ์ ํ๋ก์ธ์ค ๋ด์ ์์์ ๊ณต์ ํ๋ฉด์ ์์ ํ ๋ ์๋ก์ ์์ ์ด ๋ค๋ฅธ ์์ ์ ์ํฅ์ ์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค.
์ค๋ ๋์ ๋๊ธฐํ๋ฅผ ์ํด์ , ์๊ณ ์์ญ(critical section)๊ณผ ์ ๊ธ(lock)์ ํ์ฉํ๋ค.
์๊ณ์์ญ์ ์ง์ ํ๊ณ , ์๊ณ์์ญ์ ๊ฐ์ง๊ณ ์๋ lock์ ๋จ ํ๋์ ์ค๋ ๋์๊ฒ๋ง ๋น๋ ค์ฃผ๋ ๊ฐ๋ ์ผ๋ก ์ด๋ฃจ์ด์ ธ์๋ค.
๋ฐ๋ผ์ ์๊ณ๊ตฌ์ญ ์์์ ์ํํ ์ฝ๋๊ฐ ์๋ฃ๋๋ฉด, lock์ ๋ฐ๋ฉํด์ค์ผ ํ๋ค.
synchronized๋ฅผ ํ์ฉํด ์๊ณ์์ญ์ ์ค์ ํ ์ ์๋ค.
์๋ก ๋ค๋ฅธ ๋ ๊ฐ์ฒด๊ฐ ๋๊ธฐํ๋ฅผ ํ์ง ์์ ๋ฉ์๋๋ฅผ ๊ฐ์ด ์ค๋ฒ๋ผ์ด๋ฉํด์ ์ด์ฉํ๋ฉด, ๋ ์ค๋ ๋๊ฐ ๋์์ ์งํ๋๋ฏ๋ก ์ํ๋ ์ถ๋ ฅ ๊ฐ์ ์ป์ง ๋ชปํ๋ค.
์ด๋ ์ค๋ฒ๋ผ์ด๋ฉ๋๋ ๋ถ๋ชจ ํด๋์ค์ ๋ฉ์๋์ synchronized ํค์๋๋ก ์๊ณ์์ญ์ ์ค์ ํด์ฃผ๋ฉด ํด๊ฒฐํ ์ ์๋ค.
//synchronized : ์ค๋ ๋์ ๋๊ธฐํ. ๊ณต์ ์์์ lock
public synchronized void saveMoney(int save){ // ์
๊ธ
int m = money;
try{
Thread.sleep(2000); // ์ง์ฐ์๊ฐ 2์ด
} catch (Exception e){
}
money = m + save;
System.out.println("์
๊ธ ์ฒ๋ฆฌ");
}
public synchronized void minusMoney(int minus){ // ์ถ๊ธ
int m = money;
try{
Thread.sleep(3000); // ์ง์ฐ์๊ฐ 3์ด
} catch (Exception e){
}
money = m - minus;
System.out.println("์ถ๊ธ ์๋ฃ");
}
์ค๋ ๋๊ฐ ์๋ก ํ๋ ฅ๊ด๊ณ์ผ ๊ฒฝ์ฐ์๋ ๋ฌด์์ ๋๊ธฐ์ํค๋ ๊ฒ์ผ๋ก ์ฌ๋ฐ๋ฅด๊ฒ ์คํ๋์ง ์๊ธฐ ๋๋ฌธ์ ์ฌ์ฉํ๋ค.
wait() : ์ค๋ ๋๊ฐ lock์ ๊ฐ์ง๊ณ ์์ผ๋ฉด, lock ๊ถํ์ ๋ฐ๋ฉํ๊ณ ๋๊ธฐํ๊ฒ ๋ง๋ฌ
notify() : ๋๊ธฐ ์ํ์ธ ์ค๋ ๋์๊ฒ ๋ค์ lock ๊ถํ์ ๋ถ์ฌํ๊ณ ์ํํ๊ฒ ๋ง๋ฌ
์ด ๋ ๋ฉ์๋๋ ๋๊ธฐํ ๋ ์์ญ(์๊ณ ์์ญ)๋ด์์ ์ฌ์ฉ๋์ด์ผ ํ๋ค.
๋๊ธฐํ ์ฒ๋ฆฌํ ๋ฉ์๋๋ค์ด ๋ฐ๋ณต๋ฌธ์์ ํ์ฉ๋๋ค๋ฉด, ์๋ํ๋๋ก ๊ฒฐ๊ณผ๊ฐ ๋์ค์ง ์๋๋ค. ์ด๋ wait()๊ณผ notify()๋ฅผ try-catch ๋ฌธ์์ ์ ์ ํ ํ์ฉํด ํด๊ฒฐํ ์ ์๋ค.
/**
* ์ค๋ ๋ ๋๊ธฐํ ์ค ํ๋ ฅ๊ด๊ณ ์ฒ๋ฆฌ์์
: wait() notify()
* ์ค๋ ๋ ๊ฐ ํ๋ ฅ ์์
๊ฐํ
*/
public synchronized void makeBread(){
if (breadCount >= 10){
try {
System.out.println("๋นต ์์ฐ ์ด๊ณผ");
wait(); // Thread๋ฅผ Not Runnable ์ํ๋ก ์ ํ
} catch (Exception e) {
}
}
breadCount++; // ๋นต ์์ฐ
System.out.println("๋นต์ ๋ง๋ฆ. ์ด " + breadCount + "๊ฐ");
notify(); // Thread๋ฅผ Runnable ์ํ๋ก ์ ํ
}
public synchronized void eatBread(){
if (breadCount < 1){
try {
System.out.println("๋นต์ด ์์ด ๊ธฐ๋ค๋ฆผ");
wait();
} catch (Exception e) {
}
}
breadCount--;
System.out.println("๋นต์ ๋จน์. ์ด " + breadCount + "๊ฐ");
notify();
}
์กฐ๊ฑด ๋ง์กฑ ์ํ ์ wait(), ๋ง์กฑ ์ notify()๋ฅผ ๋ฐ์ ์ํํ๋ค.