๋ธ๋ก๊ทธ ์ฎ๊ฒผ์ต๋๋ค! ๐ก integer.blog
์๋ฐ์ ์ ์(๋จ๊ถ์ฑ ์ ) 2๊ถ ํ์ต
1. ํ๋ก์ธ์ค์ ์ฐ๋ ๋
- ํ๋ก์ธ์ค๋ ์คํ์ค์ธ ํ๋ก๊ทธ๋จ์ด๋ค.
- ํ๋ก๊ทธ๋จ์ ์คํํ๋ฉด OS๋ก๋ถํฐ ์คํ์ ํ์ํ ์์(๋ฉ๋ชจ๋ฆฌ)๋ฅผ ํ ๋น๋ฐ์ ํ๋ก์ธ์ค๊ฐ ๋๋ค.
- ํ๋ก์ธ์ค์ ์์์ ์ด์ฉํด์ ์ค์ ๋ก ์์ ์ ์ํํ๋ ๊ฒ์ด ์ฐ๋ ๋๋ค.
- ๋ชจ๋ ํ๋ก์ธ์ค์๋ ์ต์ํ ํ๋ ์ด์์ ์ฐ๋ ๋๊ฐ ์กด์ฌํ๋ค.
- ์ฐ๋ ๋๊ฐ ์์ ์ ์ํํ๋ ค๋ฉด ๊ฐ๋ณ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ(ํธ์ถ์คํ)์ด ํ์ํ๋ค.
- CPU์ ์ฝ์ด(core)๊ฐ ํ ๋ฒ์ ๋จ ํ๋์ ์์ ๋ง ์ํํ ์ ์์ผ๋ฏ๋ก, ๋์์ ์ฒ๋ฆฌ๋๋ ์์ ์ ์๋ ์ฝ์ด์ ๊ฐ์์ ์ผ์นํ๋ค.
2. ์ฐ๋ ๋์ ๊ตฌํ๊ณผ ์คํ
- ์ฐ๋ ๋๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ Thread ํด๋์ค๋ฅผ ์์๋ฐ๋ ๋ฐฉ๋ฒ๊ณผ Runnable ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
- Thread ํด๋์ค๋ฅผ ์์๋ฐ์ผ๋ฉด ๋ค๋ฅธ ํด๋์ค๋ฅผ ์์๋ฐ์ ์ ์๊ธฐ ๋๋ฌธ์, Runnable ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ด ์ผ๋ฐ์ ์ด๋ค.
2.1. Thread ํด๋์ค ์์
class MyThread extends Thread {
public void run() { // Thread ํด๋์ค์ run()์ ์ค๋ฒ๋ผ์ด๋ฉ
์์
๋ด์ฉ
}
}
2.2. Runnable ์ธํฐํ์ด์ค ๊ตฌํ
Runnable ์ธํฐํ์ด์ค๋ ์ค๋ก์ง run()๋ง ์ ์๋์ด ์๋ ๊ฐ๋จํ ์ธํฐํ์ด์ค์ด๋ค.
Runnable ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ธฐ ์ํด์ ํด์ผ ํ ์ผ์ ์ถ์๋ฉ์๋์ธ run()์ ๋ชธํต {}์ ๋ง๋ค์ด ์ฃผ๋ ๊ฒ ๋ฟ์ด๋ค.
public interface Runnable {
public abstract void run();
}
์ฐ๋ ๋๋ฅผ ๊ตฌํํ๋ค๋ ๊ฒ์ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ ๋ชจ๋, ๊ทธ์ ์ฐ๋ ๋๋ฅผ ํตํด ์์ ํ๊ณ ์ ํ๋ ๋ด์ฉ์ผ๋ก run()์ ๋ชธํต{}์ ์ฑ์ฐ๋ ๊ฒ ๋ฟ์ด๋ค.
2.3. ์ธ์คํด์ค ์์ฑ ๋ฐฉ๋ฒ
- Thread ํด๋์ค ์์
ThreadA t1 = new ThreadA();
- Runnable ์ธํฐํ์ด์ค ๊ตฌํ
Runnable r = new ThreadB();
Thread t2 = new Thread(r);
Threadํด๋์ค๋ฅผ ์์๋ฐ์ผ๋ฉด, ์์ ํด๋์ค์์ ์กฐ์์ธ Threadํด๋์ค์ ๋ฉ์๋๋ฅผ ์ง์ ํธ์ถํ ์ ์์ง๋ง,
Runnable์ ๊ตฌํํ๋ฉด Threadํด๋์ค์ static๋ฉ์๋์ธ currentThread()๋ฅผ ํธ์ถํ์ฌ ์ฐ๋ ๋์ ๋ํ ์ฐธ์กฐ๋ฅผ ์ป์ด ์์ผ๋ง ํธ์ถ์ด ๊ฐ๋ฅํ๋ค.
class ThreadA extends Thread {
public void run() {
System.out.println(getName()); // ์กฐ์์ธ Thread์ getName() ํธ์ถ
}
}
class ThreadB implements Runnable {
public void run() {
System.out.println(Thread.currentThread().getName());
// Thread.currentThread() - ํ์ฌ ์คํ์ค์ธ Thread ๋ฐํ
}
}
2.4. ์ฐ๋ ๋์ ์คํ
- ์ฐ๋ ๋๋ฅผ ์์ฑํ๋ค๊ณ ์๋์ ์คํ๋์ง ์๋๋ค. start()๋ฅผ ํธ์ถํด์ผ๋ง ์ฐ๋ ๋๊ฐ ์คํ๋๋ค.
- start()๊ฐ ํธ์ถ๋์ด๋ ๋ฐ๋ก ์คํ๋๋ ๊ฒ์ด ์๋๋ผ, ์คํ๋๊ธฐ ์ํ์ ์๋ค๊ฐ ์์ ์ ์ฐจ๋ก๊ฐ ๋์ด์ผ ์คํ๋๋ค.
- ์ฐ๋ ๋์ ์คํ ์์๋ OS์ ์ค์ผ์ฅด๋ฌ๊ฐ ์์ฑํ ์ค์ผ์ฅด์ ์ํด ๊ฒฐ์ ๋๋ค.
- ํ ๋ฒ ์คํ์ด ์ข ๋ฃ๋ ์ฐ๋ ๋๋ ๋ค์ ์คํํ ์ ์๋ค. (ํ๋์ ์ฐ๋ ๋์ start()๊ฐ ํ ๋ฒ๋ง ํธ์ถ๋ ์ ์๋ค.)
2.5. Start() ์ run()
- main๋ฉ์๋์์ run()์ ํธ์ถํ๋ ๊ฒ์ ์์ฑ๋ ์ฐ๋ ๋๋ฅผ ์คํ์ํค๋ ๊ฒ์ด ์๋๋ผ, ๋จ์ํ ํด๋์ค์ ์ ์ธ๋ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๊ฒ์ผ ๋ฟ์ด๋ค.
- start()๋ ์๋ก์ด ์ฐ๋ ๋๋ฅผ ์ํด ํธ์ถ์คํ(call stack)์ ์์ฑํ ํ์ run()์ ํธ์ถํด์, ์์ฑ๋ ํธ์ถ์คํ์ run()์ด ์ฒซ ๋ฒ์งธ๋ก ์ฌ๋ผ๊ฐ๊ฒ ํ๋ค.
- main๋ฉ์๋์์ ์ฐ๋ ๋์ start()๋ฅผ ํธ์ถํ๋ค.
- start()๋ ์๋ก์ด ์ฐ๋ ๋๋ฅผ ์์ฑํ๊ณ , ์ฐ๋ ๋๊ฐ ์์ ํ๋๋ฐ ์ฌ์ฉ๋ ํธ์ถ์คํ์ ์์ฑํ๋ค.
- ์๋ก ์์ฑ๋ ํธ์ถ์คํ์ run()์ด ํธ์ถ๋์ด, ์ฐ๋ ๋๊ฐ ๋ ๋ฆฝ๋ ๊ณต๊ฐ์์ ์์ ์ ์ํํ๋ค.
- ํธ์ถ์คํ์ด 2๊ฐ๊ฐ ๋์์ผ๋ฏ๋ก ์ค์ผ์ฅด๋ฌ๊ฐ ์ ํ ์์์ ์ํด ๋ฒ๊ฐ์ ๊ฐ๋ฉด์ ์คํ๋๋ค.
- ์ฃผ์ด์ง ์๊ฐ๋์ ์์ ์ ๋ง์น์ง ๋ชปํ ์ฐ๋ ๋๋ ๋ค์ ์์ ์ ์ฐจ๋ก๊ฐ ๋์์ฌ ๋๊น์ง ๋๊ธฐ ์ํ๋ก ์๋๋ค.
- ์์
์ ๋ง์น ์ฐ๋ ๋, ์ฆ run()์ ์ํ์ด ์ข
๋ฃ๋ ์ฐ๋ ๋๋ ์ฌ์ฉํ๋ ํธ์ถ์คํ์ด ๋ชจ๋ ๋น์์ง๊ณ ์ฌ๋ผ์ง๋ค.
- ์ด๋ ์๋ฐํ๋ก๊ทธ๋จ์ ์คํํ๋ฉด ํธ์ถ์คํ์ด ์์ฑ๋๊ณ main๋ฉ์๋๊ฐ ์ฒ์์ผ๋ก ํธ์ถ๋๊ณ , main๋ฉ์๋๊ฐ ์ข ๋ฃ๋๋ฉด ํธ์ถ์คํ์ด ๋น์์ง๋ฉด์ ํ๋ก๊ทธ๋จ๋ ์ข ๋ฃ๋๋ ๊ฒ๊ณผ ๊ฐ๋ค.
- ํ ์ฐ๋ ๋๊ฐ ์์ธ๊ฐ ๋ฐ์ํด์ ์ข ๋ฃ๋์ด๋ ๋ค๋ฅธ ์ฐ๋ ๋์ ์คํ์๋ ์ํฅ์ ๋ฏธ์น์ง ์๋๋ค.
3. ์ฐ๋ ๋์ ์คํ์ ์ด
3.1. sleep(long millis)
์ผ์ ์๊ฐ๋์ ์ฐ๋ ๋๋ฅผ ๋ฉ์ถ๊ฒ ํ๋ค.
static void sleep(long millis)
static void sleep(long millis, int nanos)
- sleep()์ ์ํด ์ผ์์ ์ง ์ํ๊ฐ ๋ ์ฐ๋ ๋๋ ์ง์ ๋ ์๊ฐ์ด ์ง๋๊ฑฐ๋, interrupt()๊ฐ ํธ์ถ๋๋ฉด, InterruptedException์ด ๋ฐ์๋์ด ์ ์์ ๊นจ์ด๋ ์คํ๋๊ธฐ ์ํ๊ฐ ๋๋ค.
- ๊ทธ๋์ sleep()์ ํธ์ถํ ๋๋ ํญ์ try-catch๋ฌธ์ผ๋ก ์์ธ๋ฅผ ์ฒ๋ฆฌํด์ค์ผ ํ๋ค.
void delay(long millis) {
try {
Thread.sleep(millis);
} catch(InterruptedException e) {}
}
- sleep()์ ํญ์ ์คํ์ค์ธ ์ฐ๋ ๋์ ๋ํด ์๋ํ๋ค.
- ๊ทธ๋์ sleep()์ static์ผ๋ก ์ ์ธ๋์ด ์์ผ๋ฉฐ,
th1.sleep(2000)
์ฒ๋ผ ์ฐธ์กฐ๋ณ์๋ฅผ ์ด์ฉํด์ ํธ์ถํ๊ธฐ ๋ณด๋ค๋Thread.sleep(2000)
๊ณผ ๊ฐ์ด ํด์ผํ๋ค.
3.2. interrupt()์ interrupted()
์ฐ๋ ๋์ ์์ ์ ์ทจ์ํ๋ค.
void interrupt() // ์ฐ๋ ๋์ interrupted ์ํ๋ฅผ false์์ true๋ก ๋ณ๊ฒฝ
boolean isInterrupted() // ์ฐ๋ ๋์ interrupted์ํ๋ฅผ ๋ฐํ
static boolean interrupted() // ํ์ฌ ์ฐ๋ ๋์ interrupted์ํ๋ฅผ ๋ฐํ ํ, false๋ก ๋ณ๊ฒฝ
- interrupt()๋ ์ฐ๋ ๋์๊ฒ ์์ ์ ๋ฉ์ถ๋ผ๊ณ ์์ฒญํ๋ค. (๊ฐ์ ์ข ๋ฃ๋ ์๋๋ค.)
- interrupted()๋ ์ฐ๋ ๋์ ๋ํด interrupt()๊ฐ ํธ์ถ๋์๋์ง ์๋ ค์ค๋ค. (์์๋ค๋ฉด false, ํธ์ถ ๋์๋ค๋ฉด true ๋ฐํ)
- ์ฐ๋ ๋๊ฐ sleep(), wait(), join()์ ์ํด ์ผ์์ ์ง(waiting) ์ํ์ ์์ ๋, ํด๋น ์ฐ๋ ๋์ ๋ํด interrupt()๋ฅผ ํธ์ถํ๋ฉด
sleep(), wait(), join()์์Interrupted Exception
์ด ๋ฐ์ํ๊ณ ์ฐ๋ ๋๋ ์คํ๋๊ธฐ(Runnable) ์ํ๋ก ๋ฐ๋๋ค.
์ฆ, ๋ฉ์ถฐ์๋ ์ฐ๋ ๋๋ฅผ ๊นจ์์ ์คํ๊ฐ๋ฅํ ์ํ๋ก ๋ง๋๋ ๊ฒ์ด๋ค.
3.3. suspend(), resume(), stop()
๋ชจ๋ deprecated ๋ ๋ฉ์๋ ๋ค์ด๋ค. - suspend()๋ sleep()์ฒ๋ผ ์ฐ๋ ๋๋ฅผ ๋ฉ์ถ๊ฒ ํ๋ค. suspend()์ ์ํด ์ ์ง๋ ์ฐ๋ ๋๋ resume()์ ํธ์ถํด์ผ ๋ค์ ์คํ๋๊ธฐ ์ํ๊ฐ ๋๋ค. - stop()์ ํธ์ถ๋๋ ์ฆ์ ์ฐ๋ ๋๊ฐ ์ข ๋ฃ๋๋ค. - suspend()์ stop()์ ๊ต์ฐฉ์ํ(Deadlock)๋ฅผ ์ผ์ผํค๊ธฐ ์ฌ์ฐ๋ฏ๋ก ๊ถ์ฅ๋์ง ์๋๋ค.
3.4. yield()
์ฐ๋ ๋ ์์ ์๊ฒ ์ฃผ์ด์ง ์คํ์๊ฐ์ ๋ค์ ์ฐจ๋ก์ ์ฐ๋ ๋์๊ฒ ์๋ณดํ๋ค.
3.5. join()
์ฐ๋ ๋ ์์ ์ด ํ๋ ์์ ์ ์ ์ ๋ฉ์ถ๊ณ ๋ค๋ฅธ ์ฐ๋ ๋๊ฐ ์ง์ ๋ ์๊ฐ ๋์ ์์ ์ ์ํํ๋๋ก ํ ๋ join()์ ์ฌ์ฉํ๋ค.
void join()
void join(long millis)
void join(long millis, int nanos)
- ์๊ฐ์ ์ง์ ํ์ง ์์ผ๋ฉด, ํด๋น ์ฐ๋ ๋๊ฐ ์์ ์ ๋ชจ๋ ๋ง์น ๋ ๊น์ง ๊ธฐ๋ค๋ฆฌ๊ฒ ๋๋ค.
- ์์ ์ค์ ๋ค๋ฅธ ์ฐ๋ ๋์ ์์ ์ด ๋จผ์ ์ํ๋์ด์ผ ํ ํ์๊ฐ ์์ ๋ join()์ ์ฌ์ฉํ๋ค.
- join()์ด ํธ์ถ๋๋ ๋ถ๋ถ์ try-catch๋ก ๊ฐ์ธ์ผํ๋ค.
- sleep()๊ณผ ๋ค๋ฅธ ์ ์ join()์ ํ์ฌ ์ฐ๋ ๋๊ฐ ์๋ ํน์ ์ฐ๋ ๋์ ๋ํด ๋์ํ๋ฏ๋ก static๋ฉ์๋๊ฐ ์๋๋ผ๋ ๊ฒ์ด๋ค.
try {
th1.join(); // ํ์ฌ ์คํ์ค์ธ ์ฐ๋ ๋๊ฐ ์ฐ๋ ๋ th1์ ์์
์ด ๋๋ ๋ ๊น์ง ๊ธฐ๋ค๋ฆฐ๋ค.
} catch(InterruptedException e) {}
4. ์ฐ๋ ๋์ ๋๊ธฐํ
ํ ์ฐ๋ ๋๊ฐ ์งํ ์ค์ธ ์์ ์ ๋ค๋ฅธ ์ฐ๋ ๋๊ฐ ๊ฐ์ญํ์ง ๋ชปํ๋๋ก ๋ง๋ ๊ฒ.
4.1. ์๊ณ์์ญ(critical section)๊ณผ ์ ๊ธ(lock)
๊ณต์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ์ฝ๋ ์์ญ์ ์๊ณ์์ญ์ผ๋ก ์ง์ ํด๋๊ณ ,
๊ณต์ ๋ฐ์ดํฐ(๊ฐ์ฒด)๊ฐ ๊ฐ์ง๊ณ ์๋ lock์ ํ๋ํ ๋จ ํ๋์ ์ฐ๋ ๋๋ง ์ด ์์ญ ๋ด์ ์ฝ๋๋ฅผ ์ํํ ์ ์๊ฒ ํ๋ค.
๊ทธ๋ฆฌ๊ณ ํด๋น ์ฐ๋ ๋๊ฐ ์๊ณ์์ญ ๋ด์ ๋ชจ๋ ์ฝ๋๋ฅผ ์ํํ๊ณ ๋ฒ์ด๋์ lock์ ๋ฐ๋ฉํด์ผ
๋ค๋ฅธ ์ฐ๋ ๋๊ฐ ๋ฐ๋ฉ๋ lock์ ํ๋ํ์ฌ ์๊ณ ์์ญ์ ์ฝ๋๋ฅผ ์ํํ ์ ์๊ฒ ๋๋ค.
4.2. Synchronized๋ฅผ ์ด์ฉํ ๋๊ธฐํ
์๊ณ์์ญ์ ์ค์ ํ๋๋ฐ ์ฌ์ฉ
1. ๋ฉ์๋ ์ ์ฒด๋ฅผ ์๊ณ ์์ญ์ผ๋ก ์ง์
public synchronized void calcSum() {
...
}
2. ํน์ ํ ์์ญ์ ์๊ณ ์์ญ์ผ๋ก ์ง์
synchronized(๊ฐ์ฒด์ ์ฐธ์กฐ๋ณ์) {
...
}
์ฐ๋ ๋๋ synchronized๋ฉ์๋๊ฐ ํธ์ถ๋ ์์ ๋ถํฐ ํด๋น ๋ฉ์๋๊ฐ ํฌํจ๋ ๊ฐ์ฒด์ lock์ ์ป์ด ์์
์ ์ํํ๋ค๊ฐ ๋ฉ์๋๊ฐ ์ข
๋ฃ๋๋ฉด lock ๋ฐํํ๋ค.
lock์ ํ๋๊ณผ ๋ฐ๋ฉ์ด ๋ชจ๋ ์๋์ผ๋ก ์ด๋ฃจ์ด์ง๋ฏ๋ก, ๊ฐ๋ฐ์๋ ๊ทธ์ ์๊ณ์์ญ๋ง ์ค์ ํด์ฃผ๋ฉด ๋๋ค.
๋ชจ๋ ๊ฐ์ฒด๋ lock์ ํ๋์ฉ ๊ฐ์ง๊ณ ์๊ณ , ํด๋น ๊ฐ์ฒด์ lock์ ๊ฐ์ง๊ณ ์๋ ์ฐ๋ ๋๋ง ์๊ณ์์ญ์ ์ฝ๋๋ฅผ ์ํํ ์ ์๋ค. ๋๋ฌธ์ ๋ค๋ฅธ ์ฐ๋ ๋๋ค์ lock์ ์ป์ ๋ ๊น์ง ๊ธฐ๋ค๋ฆฌ๊ฒ ๋๋ฏ๋ก,
๊ฐ๋ฅํ๋ฉด ๋ฉ์๋ ์ ์ฒด์ lock์ ๊ฑฐ๋ ๊ฒ ๋ณด๋ค, synchronized๋ธ๋ญ์ผ๋ก ์๊ณ์์ญ์ ์ต์ํํ๋ ๊ฒ์ด ์ข๋ค.
4.3. wait()๊ณผ notify()
๋๊ธฐํ๋ ์๊ณ์์ญ์ ์ฝ๋๋ฅผ ์ํํ๋ค๊ฐ ์์ ์ ๋ ์ด์ ์งํํ ์ํฉ์ด ์๋๋ฉด,
wait()์ ํธ์ถํ์ฌ ์ฐ๋ ๋๊ฐ lock์ ๋ฐ๋ฉํ๊ณ ๊ธฐ๋ค๋ฆฌ๊ฒ ํ๋ค.
๊ทธ๋ฌ๋ฉด ๋ค๋ฅธ ์ฐ๋ ๋๊ฐ lock์ ์ป์ด ํด๋น ๊ฐ์ฒด์ ๋ํ ์์ ์ ์ํํ ์ ์๊ฒ ๋๋ค.
๋์ค์ ์์ ์ ์งํํ ์ ์๋ ์ํฉ์ด ๋๋ฉด notify()๋ฅผ ํธ์ถํด์,
์์ ์ ์ค๋จํ๋ ์ฐ๋ ๋๊ฐ ๋ค์ lock์ ์ป์ด ์์ ์ ์งํํ ์ ์๊ฒ ํ๋ค.
wait(), notify(), notifyAll()
- ํน์ ๊ฐ์ฒด์ ๋ํ ๊ฒ์ด๋ฏ๋ก Objectํด๋์ค์ ์ ์๋์ด ์๋ค.
- ๋๊ธฐํ ๋ธ๋ก(synchronized)๋ด์์๋ง ์ฌ์ฉํ ์ ์๋ค.
void wait() // notify() ๋๋ notifyAll()์ ๊ธฐ๋ค๋ฆฐ๋ค.
void wait(long timeout)
void wait(long timeout, int nanos) // ์ง์ ๋ ์๊ฐ๋์๋ง ๊ธฐ๋ค๋ฆฐ๋ค. (์๊ฐ ์ง๋๋ฉด ์๋์ผ๋ก notify()๊ฐ ํธ์ถ๋๋ ๊ฒ๊ณผ ๊ฐ๋ค
void notify()
void notifyAll()
- waiting pool์ ๊ฐ์ฒด๋ง๋ค ์กด์ฌํ๋ฏ๋ก notifyAll()์ด ํธ์ถ๋๋ค๊ณ ๋ชจ๋ ๊ฐ์ฒด์ waiting pool์ ์๋ ์ฐ๋ ๋๊ฐ ๊นจ์์ง๋ ๊ฒ์ ์๋๋ค.
- ํธ์ถ๋ ๊ฐ์ฒด์ waiting pool์ ๋๊ธฐ ์ค์ธ ์ฐ๋ ๋๋ง ํด๋นํ๋ค.
4.4. Lock๊ณผ Condition์ ์ด์ฉํ๋๊ธฐํ
๋๊ธฐํํ ์ ์๋ ๋ฐฉ๋ฒ์ synchronized๋ธ๋ญ ์ธ์๋
java.util.concurrent.locks
ํจํค์ง๊ฐ ์ ๊ณตํ๋ lockํด๋์ค๋ค์ ์ด์ฉํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
๊ฐ์ ๋ฉ์๋ ๋ด์์๋ง lock์ ๊ฑธ ์ ์๋ synchronized๋ธ๋ญ์ ์ ์ฝ์ด ๋ถํธํ ๋ lockํด๋์ค๋ฅผ ์ฌ์ฉํ๋ค.
4.5. Lock
lockํด๋์ค์ ์ข ๋ฅ 3๊ฐ์ง
- ReentrantLock
- ์ฌ์ง์ ์ด ๊ฐ๋ฅํ lock. ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๋ฐฐํ lock
- ํน์ ์กฐ๊ฑด์์ lock์ ํ๊ณ ๋์ค์ ๋ค์ lock์ ์ป๊ณ ์๊ณ์์ญ์ผ๋ก ๋ค์ด์์ ์ดํ์ ์์ ์ ์ํํ ์ ์๋ค.
- ReentrantReadWriteLock
- ์ฝ๊ธฐ์๋ ๊ณต์ ์ , ์ฐ๊ธฐ์๋ ๋ฐฐํ์ ์ธ lock
- ์ฝ๊ธฐ lock์ด ๊ฑธ๋ฆฐ ์ํ์์ ์ฐ๊ธฐ lock์ ๊ฑฐ๋ ๊ฒ์ ํ์ฉ๋์ง ์๋๋ค. (vice versa)
- StampLock
- ReentrantReadWriteLock์ ๋๊ด์ ์ฝ๊ธฐ lock์ ์ถ๊ฐํ๋ค.
- JDK1.8๋ถํฐ ์ถ๊ฐ๋์์ผ๋ฉฐ, ๋ค๋ฅธ lock๊ณผ ๋ฌ๋ฆฌ Lock์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ์ง ์์๋ค.
- lock์ ๊ฑธ๊ฑฐ๋ ํด์งํ ๋ ์คํฌํ(longํ์ ์ ์ ์๊ฐ)๋ฅผ ์ฌ์ฉํ๋ค.
- ๋ฌด์กฐ๊ฑด ์ฝ๊ธฐ lock์ ๊ฑธ์ง ์๊ณ , ์ฐ๊ธฐ์ ์ฝ๊ธฐ๊ฐ ์ถฉ๋ํ ๋๋ง ์ฐ๊ธฐ๊ฐ ๋๋ ํ์ ์ฝ๊ธฐ lock์ ๊ฑฐ๋ ๊ฒ์ด๋ค.
์ผ๋ฐ์ ์ธ StampLock์ ์ด์ฉํ ๋๊ด์ ์ฝ๊ธฐ์ ์
int getBalance() {
long stamp = lock.tryOptimisticRead(); // ๋๊ด์ ์ฝ๊ธฐ lock์ ๊ฑด๋ค.
int curBalance = this.balance; // ๊ณต์ ๋ฐ์ดํฐ์ธ balance๋ฅผ ์ฝ์ด ์จ๋ค.
if(lock.validate(stamp)) { // ์ฐ๊ธฐ lock์ ์ํด ๋๊ด์ ์ฝ๊ธฐ lock์ด ํ๋ ธ๋์ง ํ์ธ
stamp = lock.readLock(); // lock์ด ํ๋ ธ์ผ๋ฉด, ์ฝ๊ธฐ lock์ ์ป์ผ๋ ค๊ณ ๊ธฐ๋ค๋ฆฐ๋ค.
try {
curBalance = this.balance; // ๊ณต์ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ์ฝ์ด์จ๋ค.
}finally {
lock.unlockRead(stamp); // ์ฝ๊ธฐ lock์ ํผ๋ค.
}
}
return curBalance; // ๋๊ด์ ์ฝ๊ธฐ lock์ด ํ๋ฆฌ์ง ์์์ผ๋ฉด ๊ณง๋ฐ๋ก ์ฝ์ด์จ ๊ฐ์ ๋ฐํ
}
์๋์ผ๋ก lock์ ์ ๊ธ๊ณผ ํด์ ๊ฐ ๊ด๋ฆฌ๋๋ synchronized๋ธ๋ญ๊ณผ ๋ฌ๋ฆฌ,
ReentrantLock๊ณผ ๊ฐ์ lockํด๋์ค๋ค์ ์๋์ผ๋ก lock์ ์ ๊ทธ๊ณ ํด์ ํด์ผ ํ๋ค.
์๊ณ ์์ญ ๋ด์์ ์์ธ๊ฐ ๋ฐ์ํ๊ฑฐ๋ return๋ฌธ์ผ๋ก ๋น ์ ธ๋๊ฐ๊ฒ ๋๋ฉด lock์ด ํ๋ฆฌ์ง ์์ ์ ์๋ค. ๊ทธ๋ฌ๋ฏ๋ก unlock()์ try-finally ๋ฌธ์ผ๋ก ๊ฐ์ธ๋ ๊ฒ์ด ์ผ๋ฐ ์ ์ด๋ค.
lock.lock(); //ReentrantLock lock = enw ReentrantLock();
try {
// ์๊ณ์์ญ
} finally {
lock.unlock();
}
4.6. Condition
wait()๊ณผ notify()๋ก ์ฐ๋ ๋์ ์ข ๋ฅ๋ฅผ ๊ตฌ๋ถํ์ง ์๊ณ , ๊ณต์ ๊ฐ์ฒด์ waiting pool์ ๊ฐ์ด ๋ชฐ์ ๋ฃ๋ ๋์ , ๊ฐ ์ฐ๋ ๋๋ฅผ ์ํ Condition์ ๊ฐ๊ฐ ๋ง๋ค์ด์๊ฑฐ ๊ฐ๊ฐ์ waiting pool์์ ๋ฐ๋ก ๊ธฐ๋ค๋ฆฌ๋๋ก ํ๋ค.
Condition์ ์ด๋ฏธ ์์ฑ๋ lock์ผ๋ก๋ถํฐ newCondition()์ ํธ์ถํด์ ์์ฑํ๋ค.
private ReentrantLock lock = new ReentrantLock(); // lock์ ์์ฑ
// lock์ผ๋ก condition์ ์์ฑ
private Condition forCook = lock.newCondition();
private Condition forCust = lock.newCondition();
wait()๊ณผ notify() ๋์ Condition์ await()๊ณผ signal()์ ์ฌ์ฉํ๋ฉด ๋๋ค.
4.7. volatile
๋ฉํฐ ์ฝ์ด ํ๋ก์ธ์์์๋ ์ฝ์ด๋ง๋ค ๋ณ๋์ ์บ์๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
์ฝ์ด๋ ๋ฉ๋ชจ๋ฆฌ์์ ์ฝ์ด์จ ๊ฐ์ ์บ์์ ์ ์ฅํ๊ณ ์บ์์์ ๊ฐ์ ์ฝ์ด์ ์์
ํ๋ค.
๋ค์ ๊ฐ์ ๊ฐ์ ์ฝ์ด์ฌ ๋๋ ๋จผ์ ์บ์์ ์๋์ง ํ์ธํ๊ณ ์์ ๋๋ง ๋ฉ๋ชจ๋ฆฌ์์ ์ฝ์ด์จ๋ค. ๋๋ฌธ์ ๋์ค์ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋ ๋ณ์์ ๊ฐ์ด ๋ณ๊ฒฝ๋์๋๋ฐ๋ ์บ์์ ์ ์ฅ๋ ๊ฐ์ด ๊ฐฑ์ ๋์ง ์์์ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋ ๊ฐ์ด ๋ค๋ฅธ ๊ฒฝ์ฐ๊ฐ ๋ฐ์ํ๋ค.
๋ณ์ ์์ volatile์ ๋ถ์ด๋ฉด, ์ฝ์ด๊ฐ ๋ณ์์ ๊ฐ์ ์ฝ์ด์ฌ ๋ ์บ์๊ฐ ์๋ ๋ฉ๋ชจ๋ฆฌ์์ ์ฝ์ด์ค๊ธฐ ๋๋ฌธ์ ์บ์์ ๋ฉ๋ชจ๋ฆฌ๊ฐ์ ๊ฐ์ ๋ถ์ผ์น๊ฐ ํด๊ฒฐ๋๋ค.
๋ณ์์ volatile์ ๋ถ์ด๋ ๋์ ์ synchronized๋ธ๋ญ์ ์ฌ์ฉํด๋ ๊ฐ์ ํจ๊ณผ๋ฅผ ์ป์ ์ ์๋ค.
์ฐ๋ ๋๊ฐ synchronized๋ธ๋ญ์ผ๋ก ๋ค์ด๊ฐ ๋์ ๋์ฌ ๋, ์บ์์ ๋ฉ๋ชจ๋ฆฌ๊ฐ์ ๋๊ธฐํ๊ฐ ์ด๋ฃจ์ด์ ธ์ ๊ฐ์ ๋ถ์ผ์น๊ฐ ํด์๋๊ธฐ ๋๋ฌธ์ด๋ค.
JVM์ ๋ฐ์ดํฐ๋ฅผ 4 byte(=32bit) ๋จ์๋ก ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์, int์ int๋ณด๋ค ์์ ํ์
๋ค์ ํ ๋ฒ์ ์ฝ๊ฑฐ๋ ์ฐ๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค. ์ฆ, ๋จ ํ๋์ ๋ช
๋ น์ด๋ก ์ฝ๊ฑฐ๋ ์ฐ๊ธฐ๊ฐ ๊ฐ๋ฅํ๋ค.
์ด๋ ๋ ์ด์ ๋๋ ์ ์๋ ์ต์์ ์์
๋จ์์ด๋ฏ๋ก, ์์
์ ์ค๊ฐ์ ๋ค๋ฅธ ์ฐ๋ ๋๊ฐ ๋ผ์ด๋ค ํ์ด ์๋ค.
ํ์ง๋ง ํฌ๊ธฐ๊ฐ 8byte์ธ long๊ณผ double ํ์
์ ๋ณ์๋ ํ๋์ ๋ช
๋ น์ด๋ก ๊ฐ์ ์ฝ๊ฑฐ๋ ์ธ ์ ์๋ค. ๋๋ฌธ์ ๋ณ์์ ๊ฐ์ ์ฝ๋ ๊ณผ์ ์์ ๋ค๋ฅธ ์ฐ๋ ๋๊ฐ ๋ผ์ด๋ค ์ฌ์ง๊ฐ ์๋ค.
์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ๋ณ์๋ฅผ ์ฝ๊ณ ์ฐ๋ ๋ชจ๋ ๋ฌธ์ฅ์ synchronized๋ธ๋ญ์ผ๋ก ๊ฐ์ธ๊ฑฐ๋
๋ณ์๋ฅผ ์ ์ธํ ๋ volatile์ ๋ถ์ด๋ ๊ฒ์ด๋ค.
์์์๋ volatile์ ๋ถ์ผ ์ ์๋ค. ์ฆ, ๋ณ์์ final๊ณผ volatile์ ๊ฐ์ด ๋ถ์ผ ์ ์๋ค.
์์๋ ๋ณํ์ง ์๋ ๊ฐ์ด๋ฏ๋ก ๋ฉํฐ์ฐ๋ ๋์ ์์ (thread-safe)ํ๋ค.
Synchronized๋ธ๋ญ์ ์ฌ๋ฌ ๋ฌธ์ฅ์ ์์ํํจ์ผ๋ก์จ ์ฐ๋ ๋์ ๋๊ธฐํ๋ฅผ ๊ตฌํํ๋ ๊ฒ์ด๋ค.
ํ์ง๋ง volatile์ ๋ณ์์ ์ฝ๊ฑฐ๋ ์ฐ๊ธฐ๋ฅผ ์์ํ ํ ๋ฟ, ๋๊ธฐํํ๋ ๊ฒ์ ์๋๋ค.
๊ทธ๋ฌ๋ฏ๋ก ๋๊ธฐํ๊ฐ ํ์ํ ๋, synchronized๋ธ๋ญ ๋์ volatile์ ์ฌ์ฉํ ์ ์๋ค.
4.8. fork & join ํ๋ ์์ํฌ
JDK1.7๋ถํฐ fork & join ํ๋ ์์ค์ด ์ถ๊ฐ๋์ด ํ๋์ ์์ ์ ์์ ๋จ์๋ก ๋๋ ์ ์ฌ๋ฌ ์ฐ๋ ๋๊ฐ ๋์์ ์ฒ๋ฆฌํ๋ ๊ฒ์ ์ฝ๊ฒ ๋ง๋ค์ด ์ค๋ค.
RecursiveAction ๋ฐํ๊ฐ์ด ์๋ ์์
์ ๊ตฌํํ ๋ ์ฌ์ฉ
RecursiveTask ๋ฐํ๊ฐ์ด ์๋ ์์
์ ๊ตฌํํ ๋ ์ฌ์ฉ
๋ ํด๋์ค ๋ชจ๋ compute()๋ผ๋ ์ถ์ ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์์ด์, ์์์ ํตํด ์ด ์ถ์๋ฉ์๋๋ฅผ ๊ตฌํํ๊ธฐ๋ง ํ๋ฉด ๋๋ค.
์ฐ๋ ๋๋ฅผ ์์ํ ๋ run()์ด ์๋๋ผ start()๋ก ํธ์ถํ๋ ๊ฒ์ฒ๋ผ,
fork & join ํ๋ ์์ํฌ๋ก ์ํํ ์์
๋ compute()๊ฐ ์๋ invoke()๋ก ์์ํ๋ค.
ForkJoinPool pool = new ForkJoinPool(); //์ฐ๋ ๋ ํ ์์ฑ
SumTask task = new SumTask(from, to); // ์ํํ ์์
์์ฑ
Long result = pool.invoke(task); // invoke()๋ฅผ ํธ์ถํด์ ์์
์ ์์
ForkJoinPool์ fork & joinํ๋ ์์ํฌ์์ ์ ๊ณตํ๋ thread pool๋ก,
์ง์ ๋ ์์ ์ฐ๋ ๋๋ฅผ ์์ฑํด์ ๋ฏธ๋ฆฌ ๋ง๋ค์ด ๋๊ณ ๋ฐ๋ณตํด์ ์ฌ์ฌ์ฉํ ์ ์๊ฒ ํ๋ค.
์ฐ๋ ๋ ํ์ ์ฐ๋ ๋๊ฐ ์ํํด์ผํ๋ ์์
์ด ๋ด๊ธด ํ๋ฅผ ์ ๊ณตํ๋ฉฐ,
๊ฐ ์ฐ๋ ๋๋ ์์ ์ ์์
ํ์ ๋ด๊ธด ์์
์ ์์๋๋ก ์ฒ๋ฆฌํ๋ค.
์ฐ๋ ๋ ํ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฝ์ด์ ๊ฐ์๊ฐ ๋์ผํ ๊ฐ์์ ์ฐ๋ ๋๋ฅผ ์์ฑํ๋ค.
fork()๋ ์์
์ ์ฐ๋ ๋์ ์์
ํ์ ๋ฃ๋ ๊ฒ์ด๊ณ , ์์
ํ์ ๋ค์ด๊ฐ ์์
์ ๋ ์ด์ ๋๋ ์ ์์ ๋๊น์ง ๋๋๋ค.
์ฆ, compute()๋ก ๋๋๊ณ fork()๋ก ์์
ํ์ ๋ฃ๋ ์์
์ด ๊ณ์ ๋ฐ๋ณต๋๋ค.
๋๋ ์ง ์์
์ ๊ฐ ์ฐ๋ ๋๊ฐ ๊ณจ๊ณ ๋ฃจ ๋๋ ์ ์ฒ๋ฆฌํ๊ณ
์์
์ ๊ฒฐ๊ณผ๋ join()์ ํธ์ถํด์ ์ป์ ์ ์๋ค.
fork()์ join()์ ์ฐจ์ด
fork() - ํด๋น ์์
์ ์ฐ๋ ๋ ํ์ ์์
ํ์ ๋ฃ๋๋ค. ๋น๋๊ธฐ ๋ฉ์๋
join() - ํด๋น ์์
์ ์ํ์ด ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ, ์ํ์ด ๋๋๋ฉด ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ค. ๋๊ธฐ ๋ฉ์๋
๋น๋๊ธฐ ๋ฉ์๋๋ ์ผ๋ฐ ๋ฉ์๋์ ๋ฌ๋ฆฌ ๋ฉ์๋๋ฅผ ํธ์ถ๋ง ํ ๋ฟ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์๋๋ค.
public Long compute() {
...
SumTask leftSum = new SumTask(from, half);
SumTask rightSum = new SumTask(half+1, to);
leftSum.fork(); // ๋น๋๊ธฐ ๋ฉ์๋. ํธ์ถ ํ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์๋๋ค.
return rightSum.compute()+leftSum.join(); // ๋๊ธฐ๋ฉ์๋. ํธ์ถ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ค๋ฆฐ๋ค.
}