
๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ ๊ฐ๋ฐ์ ํ๋ค ๋ณด๋ฉด, "๋ถ๋ช ํ ๊ณต์ ๋ณ์๋ฅผ ๋ฐ๊ฟจ๋๋ฐ ์ ๋ค๋ฅธ ์ค๋ ๋๋ ๋ฐ๋ ๊ฑธ ๋ชจ๋ฅด์ง?" ๊ฐ์ ๋ฌธ์ ๋ฅผ ์์ฃผ ๋ง๋๊ฒ ๋ฉ๋๋ค. ์ฌ์ค ์ด๋ CPU ์บ์ ๋๋ฌธ์ ๋๋ค. ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผํ๋ฉด์ ์์์ฑ๊ณผ ๊ฐ์์ฑ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค.
์ค๋์ ์๋ฐ์์ ์ด๋ฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ ๋ํ์ ์ธ ๋ฐฉ๋ฒ์ธ synchronized, ReentrantLock, volatile ํค์๋์ ๋ํด ์์ธํ ์์๋ณด๊ฒ ์ต๋๋ค.
ํ๋์ ์ปดํจํฐ๋ ์ฌ๋ฌ ๊ฐ์ CPU ์ฝ์ด๊ฐ ์๊ณ , ๊ฐ ์ฝ์ด๋ ์์ ๋ง์ CPU ์บ์๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ค๋ ๋๊ฐ ๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ผ๋ฉด, ํด๋น ๋ฐ์ดํฐ๋ฅผ ์์ ๋ง์ ์บ์์ ์ ์ฅํ๊ณ ์ฌ์ฉํ๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฐ๋ฐ ํ ์ค๋ ๋๊ฐ ์ด ์บ์์ ์๋ ๊ฐ์ ๋ณ๊ฒฝํด๋, ๋ณ๊ฒฝ๋ ๊ฐ์ด ๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ์ ์ฆ์ ๋ฐ์๋์ง ์์ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ๋ณ๊ฒฝ๋ ๊ฐ์ ์ฝ์ง ๋ชปํ๊ฒ ๋๋ ์ํฉ์ด ์๊ธฐ๋ ๊ฒ์ด์ฃ .
์ด๋ก ์ธํด ๋ฐ์ํ๋ ๋ํ์ ์ธ ๋ฌธ์ ๊ฐ ์์์ฑ(Atomicity)๊ณผ ๊ฐ์์ฑ(Visibility)์ ๋๋ค.
์ด๋ฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์๋ฐ๋ ๋ค์ํ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋๋ฐ์, ๋ํ์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก๋ synchronized, ReentrantLock, ๊ทธ๋ฆฌ๊ณ volatile ํค์๋๊ฐ ์์ต๋๋ค.
synchronized๋ ๊ฐ๋จํ๊ฒ ๋ฉ์๋ ๋๋ ์ฝ๋ ๋ธ๋ก์ ํ ๋ฒ์ ํ๋์ ์ค๋ ๋๋ง ์ ๊ทผํ ์ ์๋๋ก ์ ํํฉ๋๋ค. ์ด ๋ฐฉ์์ ์์์ฑ๊ณผ ๊ฐ์์ฑ์ ๋ชจ๋ ๋ณด์ฅํฉ๋๋ค.
class Counter {
private int count = 0;
public synchronized void increment() {
count++; // ์ด ์ฐ์ฐ์ ์์์ ์ด๋ฉฐ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ๋ฐฉํดํ์ง ๋ชปํฉ๋๋ค.
}
public synchronized int getCount() {
return count; // ๋ค๋ฅธ ์ค๋ ๋๋ ํญ์ ์ต์ ๊ฐ์ ํ์ธ ๊ฐ๋ฅ
}
}
ReentrantLock์ synchronized๋ณด๋ค ๋ ์ ์ฐํ ๋ฝ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค. ๋ฝ ํ๋ ๋ฐ ํด์ ๋ฅผ ๋ช
์์ ์ผ๋ก ์ ์ดํ ์ ์์ผ๋ฉฐ, ์กฐ๊ฑด๋ณ๋ก ์ ๊ธ์ ๋๋๊ฑฐ๋ ์ธํฐ๋ฝํธ ๊ฐ๋ฅํ ๋ฝ๊ณผ ๊ฐ์ ์ถ๊ฐ ๊ธฐ๋ฅ๋ ์ ๊ณตํฉ๋๋ค.
์์ ์ฝ๋:
import java.util.concurrent.locks.ReentrantLock;
public class SafeCounter {
private int count = 0;
private final ReentrantLock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++; // ์์์ฑ์ ๋ณด์ฅํฉ๋๋ค.
} finally {
lock.unlock();
}
}
public int getCount() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
}
volatile ํค์๋๋ ๊ฐ์์ฑ๋ง ๋ณด์ฅํฉ๋๋ค. ์ฆ, ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์ต์ ๋ณ๊ฒฝ ์ฌํญ์ ์ฆ์ ๋ณผ ์ ์๋๋ก ๋ณด์ฅํ์ง๋ง, ์์์ฑ์ ๋ณด์ฅํ์ง๋ ์์ผ๋ฏ๋ก ์ฃผ์๊ฐ ํ์ํฉ๋๋ค.
public class FlagManager {
private volatile boolean flag = false;
public void activate() {
flag = true; // ์ฆ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ฐ์๋์ด ๋ชจ๋ ์ค๋ ๋๊ฐ ํ์ธ ๊ฐ๋ฅ
}
public boolean isFlagSet() {
return flag;
}
}
๋๊ธฐํ ์์ ์ ๋๋ฌด ๋ง์ด ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ์ด ๋จ์ด์ง ์ ์์ผ๋ฏ๋ก ๊ผญ ํ์ํ ๊ณณ์๋ง ์ ์ฉํด์ผ ํฉ๋๋ค. ๋ํ ์๋ชป๋ ๋๊ธฐํ ์ฌ์ฉ์ ๊ต์ฐฉ ์ํ(Deadlock)๋ฅผ ์ผ๊ธฐํ ์ ์์ผ๋ฏ๋ก, ํญ์ ์ ์คํ๊ฒ ์ค๊ณํด์ผ ํฉ๋๋ค.
์๋ฐ์ ๋ฉํฐ์ค๋ ๋ฉ ํ๊ฒฝ์์ ๋ฐ์ํ๋ ๋์์ฑ ๋ฌธ์ ๋ ์ด๋ ต๊ณ ๊น๋ค๋กญ์ง๋ง, ์ ๋ฐฉ๋ฒ๋ค์ ์ ์ ํ ์ฌ์ฉํ๋ฉด ์์ฃผ ๊น๋ํ๊ฒ ํด๊ฒฐํ ์ ์์ต๋๋ค. ๋ค์ ํ๋ก์ ํธ์์๋ ์์์ฑ๊ณผ ๊ฐ์์ฑ ๋ฌธ์ ๋ก ๊ณ ๋ฏผํ์ง ๋ง์๊ณ , ์ด ๋ธ๋ก๊ทธ์์ ์ค๋ช ํ ๋ฐฉ๋ฒ๋ค์ ์ ๊ทน์ ์ผ๋ก ํ์ฉํด ๋ณด์ธ์! ๐ช