DevLog ๐ถ
[์ดํฉํฐ๋ธ์๋ฐ] ์์ดํ 78. ๊ณต์ ์ค์ธ ๊ฐ๋ณ ๋ฐ์ดํฐ๋ ๋๊ธฐํํด ์ฌ์ฉํ๋ผ (1) ๋ณธ๋ฌธ
[์ดํฉํฐ๋ธ์๋ฐ] ์์ดํ 78. ๊ณต์ ์ค์ธ ๊ฐ๋ณ ๋ฐ์ดํฐ๋ ๋๊ธฐํํด ์ฌ์ฉํ๋ผ (1)
dolmeng2 2023. 3. 26. 21:24๐ฌ ์ดํฉํฐ๋ธ์๋ฐ ์์ดํ 78์ ์ฝ๊ณ ์ ๋ฆฌํ ๊ธ์ ๋๋ค.
์ด๋ฒ ์ ๋ฆฌ๋ ์ฑ ๊ณผ๋ ๋ค์ ๋ค๋ฅธ ๋ด์ฉ์ ๋๋ค :D
๊ฐ๋ ์์ฒด๊ฐ ์ด๋ ค์ด ๋ถ๋ถ์ด์ด์ ์ฑ ์ ์ฝ์ผ๋ฉฐ ๊ถ๊ธํ ๋ถ๋ถ์ ๋ํด ์กฐ์ฌํ๋ ์์ผ๋ก ์์ฑํ์์ต๋๋ค ๐โ๏ธ
๋ ํธ์ผ๋ก ๋๋์ด์ ํฌ์คํ ํ ์์ ์ ๋๋ค!
์์ง ๋ฏธํกํ ์ ์ด ๋ง์์, ๋ ์ ํํ ์ ๋ณด๋ฅผ ์๊ฒ ๋๋ฉด ๋ณธ ๊ฒ์๊ธ์ ์์ ํ ์์ ์ ๋๋ค.
โ๏ธ ๋๊ธฐํ๋ ๋ฌด์์ผ๊น?
ํ์ฌ ์์ก์ด 10000์์ด๊ณ , ๊ฐ๊ฐ 1000์์ฉ ์ ๊ธํ๋ ํ์๋ฅผ 5000๋ฒ, 1000์์ฉ ์ถ๊ธํ๋ ํ์๋ฅผ 5000๋ฒ ๋ฐ๋ณตํ๋ค๊ณ ๊ฐ์ ํด๋ณด์. ๋์ผํ ๊ธ์ก์ ๋ํด ๋์ผํ ํ์๋ก 5000๋ฒ์ฉ ์งํํ๊ธฐ ๋๋ฌธ์, ์ฐ๋ฆฌ์ ์์ก์๋ ๋ณํ๊ฐ ์๋ค๊ณ ์๊ฐํ ์ ์๋ค.
[synchronized ํค์๋ ๋ถ์ด๊ธฐ ์ ]
public class Main {
public static void main(String[] args) {
Bank bank = new Bank();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
bank.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
bank.decrement();
}
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(bank.getMoney());
}
public static class Bank {
private int money = 10000;
public void increment() {
money += 1000;
}
public void decrement() {
money -= 1000;
}
public int getMoney() {
return money;
}
}
}
๊ทธ๋ฌ๋, ์ฐ๋ฆฌ์ ์์๊ณผ ๋ค๋ฅด๊ฒ ์ด์ํ ๊ฐ์ด ํ์ด๋์จ ๊ฒ์ ๋ณผ ์ ์๋ค. ์ฌ์ง์ด, ์คํํ ๋๋ง๋ค ๊ฐ์ด ๋ค๋ฅด๊ฒ ๋์จ๋ค.
์ฌ๊ธฐ์, ๊ฐ์ธ์ ์ผ๋ก ์ฌ๋ฌ ๊ฐ์ง ์คํ์ ํ๋ฉด์ ์ ๊ธฐํ๋ ์ ์ด ์์๋ค.
๋ฐ๋ณต๋ฌธ์ ๋ช ๋ฒ ๋๋์ง์ ๋ฐ๋ผ์๋ ๊ฒฐ๊ณผ๊ฐ ๊ฐ๋ฆฌ๋ ๊ฒ์ด๋ค.
๋ฐ๋ณต๋ฌธ์ ๊ฐ๊ฐ 1000๋ฒ์ฉ ๋๊ฒ ๋๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
์ฐ๋ฆฌ๊ฐ ์ํ๋๋๋ก ๊ฒฐ๊ณผ๊ฐ ๋์ค๋ ๊ฒ์ด๋ค. ์์ง? (์ฌ๋ฌ ๋ฒ ๋๋ ธ๋๋ฐ๋ ๊ณ์ ์ด๋ ๊ฒ ๋์๋ค ใ ใ )
๋ด ์๊ฐ์ผ๋ก ๋ฃจํ์ ํ์ ์์ฒด๋ thread-safe์ ์ํฅ์ ์ฃผ์ง๋ ์์ ๊ฒ์ด๋ค.
์๋ง ๋ฐ๋ณต๋ฌธ์ ํ์๊ฐ ์ ๋ค ๋ณด๋๊น ์ค๋ ๋๊ฐ ์ฐ์ฐ์ ์ผ์น๋ก ์์ฐจ์ ์ผ๋ก ์ ์คํ๋ ์ ์๋๋ก ์ค์ผ์ค๋ง์ด ๋์์ ๊ฒ ๊ฐ๋ค. (์ด๊ฒ JVM ↔ OS ์ฌ์ด์ ์ค์ผ์ค๋ง์ ํ๊ฒฝ๋ง๋ค ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๋ด ๋ ธํธ๋ถ์ด ์๋๋ผ, ๋ค๋ฅธ ๋ ธํธ๋ถ์ด์์ผ๋ฉด 1000๋ฒ์ ๋๋ ค๋ thread-safe ํ์ง ์๊ฒ ๊ฒฐ๊ณผ๊ฐ ๋์ฌ ์๋ ์๊ณ , 5000๋ฒ์ ๋๋ ค๋ thread-safe ํ ๊ฒ์ฒ๋ผ ๋์ฌ ์๋ ์๋ค.
๊ฐ์ด ์คํฐ๋๋ฅผ ์งํํ๋ ๊ทธ๋ ์ด๋ ๋ค๋ฅด๊ฒ ๋์๋ค๊ณ ํ ๊ฒ์ ๋ณด์, OS ํ๊ฒฝ์ ๋ฐ๋ผ ๋ค๋ฅธ ๊ฒ์ผ๋ก ๋ณด์ธ๋ค!
๋ค์ ๋์๊ฐ์, ์ ์ ๋ฐ ์์ํ ๊ฐ์ด ํ์ด๋์๋์ง ๊ณ ๋ฏผํด๋ณด์.
money -= 1000;
์ด ์ฝ๋๋ ์ด๋ป๊ฒ ๋ณด๋ฉด ๋จ์ํ 1000์ฉ ๊ฐ์ด ๊ฐ์ํ๋ ๋ก์ง๋ง ์คํ๋ ๊ฒ ๊ฐ์ง๋ง, ์ค์ ๋ก๋ ์ด 3๊ฐ์ง์ ์ฐ์ฐ์ด ์คํ๋๋ค.
1. ‘money’ ๋ณ์๋ฅผ ๋ฉ๋ชจ๋ฆฌ์์ ์ฝ๋๋ค.
2. ์ฝ์ ‘money’ ๋ณ์๋ฅผ ๊ฐ์์ํจ๋ค.
3. ์ ๋ฐ์ดํธ๋ ‘money’ ๋ณ์๋ฅผ ๋ค์ ๋ฉ๋ชจ๋ฆฌ์ ์ด๋ค.
์ค์ ๋ก ๋ฐ์ดํธ์ฝ๋์ ์ผ๋ถ๋ฅผ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋์ํ๋ค.
GETFIELD๋ก ์ ์ธ๋ ๋ณ์๋ฅผ ๊ฐ์ ธ์ค๊ณ , ISUB์ ํตํด์ ๊ฐ์ ๋นผ๊ณ , ๋บ ๊ฐ์ ๋ค์ PUTFIELD์ผ๋ก ์ฐ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์์ ์ํฉ์ ํด๋นํ๋ ๊ทธ๋ฆผ์ ๊ฐ๋จํ๊ฒ ๊ทธ๋ ค๋ณด์๋ค. ๋ ์ค๋ ๋๋ ์๋ก ๋ ๋ฆฝ์ ์ผ๋ก ์คํ๋๋ค.
์ฐ๋ฆฌ๋ ์ค๋ ๋ 1์ด ๊ฐ์ ๋บ ๋ค์์ ์ค๋ ๋ 2๊ฐ ๊ฐ์ ์ฝ๊ธฐ๋ฅผ ์ํ๊ฒ ์ง๋ง, ์ค์ ๋ก๋ ์ค๋ ๋ 1์ด Money๋ผ๋ ๋ณ์์ ์ฝ๊ณ , ๋บ ๋ค์์ ๊ฐ์ ๋ค์ ์ ๋ฐ์ดํธ ํ๊ธฐ ์ ์ ์ค๋ ๋ 2๊ฐ ๊ฐ์ ์ฝ๊ฒ ๋๋ฉด ๋ ์ค๋ ๋ ๋ชจ๋ '10000'์ด๋ผ๋ ๊ฐ์ ์ฝ๊ฒ ๋๋ค.
์๋ก ํ์ด๋ฐ์ด ์ข์ง ์๊ฒ ๊ฐ์ ์ฝ๊ณ , ์ฐ๋ค ๋ณด๋๊น ์์ ๊ฐ์ด ์ด์ํ ๊ฐ์ด ๋์ถ๋๋ ๊ฒ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด, ์ด๋ป๊ฒ ์์ฐจ์ ์ผ๋ก ์คํํ ์ ์์๊น?
์ฐ๋ฆฌ๋ synchronized๋ผ๋ ํค์๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
synchronized ํค์๋๋ ๋ฉ์๋๋ ๋ธ๋ก์ ํ ๋ฒ์ ํ ์ค๋ ๋์ฉ๋ง ์ํํ๋๋ก ๋ณด์ฅํ๋ค.
[synchronized ํค์๋๋ฅผ ๋ถ์ธ ํ]
public class Main {
public static void main(String[] args) {
Bank bank = new Bank();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
bank.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
bank.decrement();
}
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(bank.getMoney());
}
public static class Bank {
private int money = 10000;
public synchronized void increment() {
money += 1000;
}
public synchronized void decrement() {
money -= 1000;
}
public int getMoney() {
return money;
}
}
}
ํ ๋ฒ์ ํ๋์ ์ค๋ ๋๋ง ์คํ๋๋๋ก ๋ณด์ฅํ๊ธฐ ๋๋ฌธ์, ๋ฉ์๋์ ์คํ ์์๋ ์ผ๊ด๋๊ณ ๊ณต์ ๋ณ์์ ๋ํด์๋ ์ํ๋ ๋๋ก ์ ๊ทผ๋๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ๋๋ถ์ ์ฌ๋ฌ ๋ฒ ์คํ์ ๊ฑฐ์น๋๋ผ๋ ๊ณ์ 10000์ด๋ผ๋ ๊ฒฐ๊ณผ๊ฐ ๋ณด์ฅ๋๋ค.
๋ฐ์ดํธ ์ฝ๋๋ฅผ ์ดํด๋ณด์.
์๊น์ ๋ค๋ฅด๊ฒ synchronized๋ผ๋ ํค์๋๊ฐ ๋ถ์ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ฌ์ค ๊ทธ์ธ ๋ฐ์ดํธ ์ฝ๋์ ์ฐจ์ด๋ ๊ฑฐ์ ๋์ง ์๋๋ค. ๋ด๋ถ์ ์ผ๋ก synchronized ํค์๋๋ฅผ ๋ถ์ฌ๋ฃ๊ณ ์์์ ๋ฝ์ ๊ด๋ฆฌํ๋ ๊ฒ์ผ๋ก ํ๋จ๋๋ค.
์ฐ๋ฆฌ๋ ์ด๋ ๊ฒ ์์ฐจ์ ์ผ๋ก ์ค๋ ๋๊ฐ ์คํ๋๋ ๊ฒ์ ๋ณด์ฅํ๋ ๊ฒ์ ‘๋๊ธฐํํ๋ค’๋ผ๊ณ ํํํ ์ ์๋ค. ์ผ์ข ์ lock์ ๊ฑด๋ค๊ณ ๋ณผ ์ ์๋ค.
์๋ฐ์ Lock ์ธํฐํ์ด์ค๋ฅผ ๊ฐ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ฃผ์์ด ์์ฑ๋์ด ์๋ค. (synchronized๊ฐ ์๋ฐ์ Lock ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ์๋๋ค! ๊ทธ์ , ๋น์ทํ ๊ฐ๋ ์ด๊ธฐ ๋๋ฌธ์ ์ค๋ช ํ๊ณ ์ ํ๋ ๊ฒ์ด๋ค.)
Lock์ ๊ณต์ ๋ฆฌ์์ค์ ๋ํด ์ฌ๋ฌ ์ค๋ ๋์์ ์ฌ์ฉ๋ ๋ ์ ์ดํ๋ ๋๊ตฌ์ด๋ค.
์ด๋ ๊ณต์ ๋ ๋ฆฌ์์ค์ ๋ํ ‘๋ ์ ์ ์ธ ์ ๊ทผ’์ ์ ๊ณตํ๋ค.
์ฌ๊ธฐ์ ์ค์ํ ๊ฒ์ ๊ณต์ ๋ฆฌ์์ค์ ๋ํ ๋ ์ ์ ์ธ ์ ๊ทผ์ ์ ๊ณตํ๋ค๋ ๊ฒ์ด๋ค.
๋๊ธฐํ๋ ์ด๋ฐ ์์ผ๋ก ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๊ฐ์ ๋ณ์๋ฅผ ์์ ํ๋๋ผ๋, ํญ์ ์ ์์ ์ผ๋ก ์ ์ฅ๋ ๊ฐ์ ๋ถ๋ฌ์ค๋๋ก ์์์ฑ์ ๋ณด์ฅํ๊ฒ ๋๋ค.
๋ณธ ์ฑ ์์๋, ์๋ฐ๋ long, double์ ์ ์ธํ ๋ณ์๋ฅผ ์ฝ๊ณ ์ฐ๋ ๊ฒ์ด ์์์ ์ด๋ผ๊ณ ํํํ๋ค. ์์ผ๊น?
์๋ฐ์ primitive type์ ์๊ฐํด๋ณด์.
JVM์ ๋ฐ์ดํฐ๋ฅผ 4๋ฐ์ดํธ ๋จ์๋ก ์ฒ๋ฆฌํ๋ค. (=32๋นํธ๋งํผ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ค.)
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ 32๋นํธ ์ดํ์ธ boolean, byte, short, char, int, float์ ๊ฒฝ์ฐ ํ ๋ฒ์ ์ฒ๋ฆฌํ ์ ์๊ฒ ๋๋ค. ํ๋์ ๋ช ๋ น์ด๋ ์ต์ ๋จ์์ ์์ ์ด๊ธฐ ๋๋ฌธ์, ์์ ์ค๊ฐ์ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ๋ผ์ด๋ค ์ ์์ด์ ์์์ฑ์ ๋ณด์ฅํ๊ฒ ๋๋ค.
๊ทธ๋ฌ๋, long๊ณผ double์ ๊ฒฝ์ฐ 64๋นํธ์ด๊ธฐ ๋๋ฌธ์ ํ ๋ฒ์ ์ฒ๋ฆฌํ ์๊ฐ ์์ด์ ์์์ฑ์ ๋ณด์ฅํ์ง ๋ชปํ๋ค.
์ด๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํด์ ‘volatile’์ด๋ผ๋ ํค์๋๋ฅผ ์ ๊ณตํ๋ค. (ํน์ AtomicLong, AtomicDouble ๊ฐ์ ํด๋์ค๋ฅผ ์ฌ์ฉํด๋ ๋๋ค.) ์ฐ์ ์ด์ ๋ํด์๋ ๋ฎ์ด๋์. (๋ค์ ํฌ์คํ ์์ ์ ๋๋ก ๋ค๋ฃจ์ด๋ณด๊ฒ ์ต๋๋ค!)
โ๏ธ ๋๊ธฐํ๋ฅผ ์ด๋ป๊ฒ ํ ์ ์์๊น?
๋จผ์ , ๋จ์ํ๊ฒ ํ๋์ ์ค๋ ๋๊ฐ ์ผ์ ํ๋ ๋์ ๋ค๋ฅธ ์ค๋ ๋๋ฅผ ๋ฉ์ถ๋ค๊ณ ์๊ฐํด๋ณด์.
ํ์ฌ๋ deprecated๋ Thread.stop()์ด๋ผ๋ ๋ฉ์๋๊ฐ ์กด์ฌํ๊ธฐ๋ ํ์ง๋ง, ์ด๊ฑด ๋งค์ฐ ์ํํ ๋ฐฉ๋ฒ์ด๊ธฐ ๋๋ฌธ์ ํ๋๋ฅผ ํตํด์ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class Main {
private static boolean isStop = false;
public static void main(String[] args) throws IOException, InterruptedException {
Thread thread = new Thread(() -> {
int count = 0;
while (!isStop) {
count++;
}
});
thread.start();
TimeUnit.SECONDS.sleep(1);
isStop = true;
}
}
1์ด ํ์ true๋ก ํ๋๊ทธ๊ฐ ๋ณ๊ฒฝ๋๋ฉด์ ์ข ๋ฃ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ ์ ์๋ค.
๊ทธ๋ฌ๋, ์ด ์น๊ตฌ๋ ์ข ๋ฃ๋์ง ์๋๋ค. ๊ณ์ ์คํ์ด ๋ ๋ฟ์ด๋ค.
์ฑ ์์๋ ์๋์ ์ฝ๋๊ฐ JVM์ด ํธ์ด์คํ ์ ํตํด ์ต์ ํํ ์ฝ๋๋ผ๊ณ ์๊ฐํ๋ค.
//before
while (!isStop) {
count++;
}
// after
if (!isStop) {
while (true) {
count++;
}
}
๊ฐ์ธ์ ์ผ๋ก, ์ ์ด๋ฅผ ํธ์ด์คํ ์ด๋ผ๊ณ ํ๋์ง ์ ์ดํด๊ฐ ๋์ง ์์๋ค. ํธ์ด์คํ ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์๋ฐ์คํฌ๋ฆฝํธ์์ ๋ง์ด ์ฌ์ฉ๋๋ ๊ฐ๋ ์ด๋ค.
๐ฌ ์ด๋ฅผ ์ ํธ์ด์คํ ์ด๋ผ๊ณ ์ค๋ช ํ๋ ๊ฒ์ผ๊น?
ํธ์ด์คํ ์, ๋ณ์๋ ํจ์๋ฅผ ์ ์ธํ๊ธฐ ์ ์ ์ฌ์ฉํ ์ ์๋๋ก ๋ง๋๋ ์ต์ ํ ๊ธฐ์ ์ด๋ค.
์๋ฐ์์ ๋ณ์๋ ํธ์ด์คํ ์ด ์ ๋์ง๋ง, ํจ์์ ๊ฒฝ์ฐ ์ ์ธํ๊ธฐ ์ ์ ํธ์ถํ ์ ์๊ธฐ ๋๋ฌธ์ ํธ์ด์คํ ์ด ๊ฐ๋ฅํ๋ค.
๊ทธ๋ฌ๋ ์ฑ ์์ ์ค๋ช ํ๋ ํธ์ด์คํ ์, ๋ฃจํ ๋ด์์ ํํ ํ์๊ฐ ์๋ ์ฐ์ฐ๋ค์ ๋ฃจํ ๋ด๋ถ๊ฐ ์๋ ์ธ๋ถ์์ ์คํํ์๋ ๊ฒ์ด๋ค.
JIT ์ปดํ์ผ๋ฌ๊ฐ ์ ๋ ๊ฒ ๋ฃจํ ๋ฐ์ผ๋ก ๊บผ๋ธ ๋๋ถ์ ๋๋์ง ์๊ฒ ๋๋ ๊ฒ์ด๋ค.
์ฌ๊ธฐ์ ์ฌ์ฉํ -Djava.compiler๋ JVM์์ ์ฌ์ฉ๋๋ ์ปดํ์ผ๋ฌ์ ์ต์ ์ ์ ํํ๋ค.
java -Djava.compiler=<compiler-name> <class-name>
NONE์ผ๋ก ํ๊ฒ ๋๋ฉด, JIT ์ปดํ์ผ๋ฌ๋ฅผ ๋นํ์ฑํํ๊ฒ ๋๋ค.
๐ฌ JIT ์ปดํ์ผ๋ฌ๋?
์๋ฐ์ ์ปดํ์ผ ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ์ด ์ด๋ฃจ์ด์ง๋ค.
1) ์๋ฐ ์์ค์ฝ๋ (.java) ํ์ผ์ ์๋ฐ ์ปดํ์ผ๋ฌ๊ฐ .class ํ์ผ๋ก ์ปดํ์ผ [์ฌ๊ธฐ๊น์ง ์ปดํ์ผ ํ์์ ์คํ]
2) ์ด๋, ์ด๋ ๋ฐ์ดํธ ์ฝ๋ ํ์์ด๋ฉฐ ์ปดํ์ผ๋ ๋ฐ์ดํธ ์ฝ๋๋ฅผ JVM์ ํด๋์ค ๋ก๋์๊ฒ ์ ๋ฌํ๋ค. [๋ฐํ์์ ์คํ]
3) ํด๋์ค ๋ก๋๋ ๋ค์ด๋๋ฏน ๋ก๋ฉ์ ํตํด ํ์ํ ํด๋์ค๋ค์ ๋ก๋ฉ ๋ฐ ๋งํฌํ์ฌ, JVM์ ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ฆฐ๋ค.
4) JVM ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ผ์จ ๋ฐ์ดํธ ์ฝ๋๋ฅผ ๋ช ๋ น์ด ๋จ์๋ก ๋๋์ด ์คํ๋๋๋ฐ, ์ด๋ 2๊ฐ์ง์ ์คํ ์์ง์ ์ฌ์ฉํ๋ค.
์ฒซ ๋ฒ์งธ๋ก, ์ธํฐํ๋ฆฌํฐ๋ฅผ ํตํด์ ๋ฐ์ดํธ ์ฝ๋๋ฅผ ํ ์ค์ฉ ์ฝ๋๋ค. ๋ง์ฝ ํด๋น ๋ฉ์๋๊ฐ ์ผ์ ํ์ ์ด์ ํธ์ถ์ด ๋๋ค๋ฉด, JIT ์ปดํ์ผ๋ฌ๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋๋ฐ ์ด๋ ์ต์ ํ๋ ๊ธฐ๊ณ์ด ์ฝ๋๋ฅผ ๋ณํํด์ฃผ๊ฒ ๋๋ค. ํ ์ค์ฉ ์ฝ๋ ์ธํฐํ๋ฆฌํฐ์ ๋ฌ๋ฆฌ, JIT ์ปดํ์ผ๋ฌ๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด ๋ฐ์ดํธ ์ฝ๋๋ฅผ ํจ์๋ ํ์ผ ๋จ์๋ก ์ปดํ์ผํ๋ค. ์ด๋, ๋ฐ๋ณต๋๋ ๋ฉ์๋์ ๋ํด์๋ ๋ด๋ถ์ ์ผ๋ก ์บ์ฑ์ ์งํํ๊ธฐ ๋๋ฌธ์ ์ต์ ํ๊ฐ ๊ฐ๋ฅํ๋ค.
์๋ฌดํผ, JIT ์ปดํ์ผ๋ฌ๋ ๋ด๋ถ์ ์ผ๋ก ์๋ฐ ํ๋ก๊ทธ๋จ์ ์คํ ์ฑ๋ฅ์ ํฅ์์ํค๊ธฐ ์ํด์ ๋ฃจํ ์์์ ๋ฐ๋ณต๋๋ ์ฐ์ฐ์ ๋ฃจํ ๋ฐ์ผ๋ก ๊บผ๋ด ์ต์ ํ๋ฅผ ์งํํ๋ค. ๋ฃจํ ์์์ ์ฐ์ฐ์ ๋ฐ๋ณตํ ๋๋ง๋ค ํด๋น ์ฐ์ฐ์ ์ฌ์ํํ๋ ๊ฒ์ด ๋นํจ์จ์ ์ด๊ธฐ ๋๋ฌธ์ ๋ฃจํ ๋ฐ์์ ๋ฏธ๋ฆฌ ๊ณ์ฐํ๊ณ ์ต์ ํํ๋ ๊ฒ์ด๋ค. ์ด๋ฌํ ์ต์ ํ ๋ฐฉ๋ฒ์ ํธ์ด์คํ ์ด๋ผ๊ณ ํ๋ค.
์ฝ๋๋ก ๊ฐ๋จํ๊ฒ ์ดํด๋ณด์.
for (int i = 0; i < 1000000; i++) {
int a = 10;
int b = 20;
int c = a + b;
result += c;
}
๋ค์๊ณผ ๊ฐ์ด ๋ฃจํ ๋ด๋ถ์์ a, b๋ผ๋ ๋ณ์๋ฅผ ๊ณ์ ์ ์ธํ๋ค๊ณ ์๊ฐํด๋ณด์. ์ด ์ฝ๋๋ฅผ ํธ์ด์คํ ์ ํตํด ๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝํ ์ ์๋ค.
int a = 10;
int b = 20;
for (int i = 0; i < 1000000; i++) {
int c = a + b;
result += c;
}
์ด๋ ๊ฒ ๋ฃจํ ๋ด์์ ๊ตณ์ด ํํ ํ์๊ฐ ์๋ ์ฐ์ฐ์ ๋ํด์ ๋ฐ๊นฅ์ผ๋ก ๋นผ๋ฒ๋ฆฌ๋ ๊ฒ์ด๋ค.
์ฐ๋ฆฌ๊ฐ ์์์ ๋ดค๋ ์ฝ๋๋ฅผ ์๊ฐํด๋ณด์.
while (!isStop) {
count++;
}
JIT ์ปดํ์ผ๋ฌ๋ ๋ฃจํ ๋ด๋ถ์์ ๊ณ์ isStop ๋ณ์์ ๋ํด ์ฒดํฌํ๋ ๊ฒ์ ๋นํจ์จ์ ์ด๋ผ๊ณ ํ๋จํ๋ค. ์๋ํ๋ฉด, ์ฑ๊ธ ์ค๋ ๋ ํ๊ฒฝ์ด๋ผ๋ฉด ์ ์ด๊ฐ ์ ์ฝ๋๊น์ง ๋ด๋ ค์์ ๋ ์ธ๋ถ ์์ธ์ผ๋ก ์ธํด isStop์ด๋ผ๋ ๋ณ์๊ฐ ๋ณ๊ฒฝ๋ ์ผ์ด ์๊ธฐ ๋๋ฌธ์ด๋ค.
if (!isStop) {
while (true) {
count++;
}
}
๊ทธ๋์ JIT ์ปดํ์ผ๋ฌ๋ ๋ฃจํ ๋ด๋ถ์์ ๊ฐ์ ์ฒดํฌํ์ง ์๊ณ , ์ธ๋ถ์์ 1๋ฒ๋ง ์ฒดํฌํ ๋ค์์ ํ์์์ while๋ฌธ์ผ๋ก ๊ณ์ ๋ฐ๋ณตํ๊ฒ ๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ์ ์ฝ๋์์ ๋ฉ์ธ ์ค๋ ๋๊ฐ isStop์ด๋ผ๋ ๋ณ์๋ฅผ true๋ก ๋ณ๊ฒฝํ๋๋ผ๋, ์ด๋ฏธ if๋ฌธ์ ์กฐ๊ฑด์ ๋๋ฌ๊ธฐ ๋๋ฌธ์ ๋ฌดํ๋ฃจํ์ ๋น ์ ธ๋ฒ๋ฆฌ๊ณ ๋ง๋ ๊ฒ์ด๋ค.
์ด๋ ๊ธฐ ๋๋ฌธ์ ๋ฉํฐ ์ค๋ ๋ ํ๊ฒฝ์์๋ ์ปดํ์ผ๋ฌ ์ ๋ต์ ์ ์ ํํด์ผ ํ๋ค...!
์ฑ๋ฅ ํฅ์์ ์ ์ฉํ์ง๋ง, ์ด๋ฐ ์์ผ๋ก ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์, ๋ค์ ๋์๊ฐ์ ์์ ๊ทธ๋ฆผ์ ๋ค์ ๋ณด์.
JIT ์ปดํ์ผ๋ฌ ์ต์ ์ ๊ป๊ธฐ ๋๋ฌธ์ ์ฒซ ๋ฒ์งธ ์คํ์์๋ ๋ฐ๋ก ์ข ๋ฃ๊ฐ ๋๋ ๊ฒ์ ๋ณผ ์ ์์ง๋ง, ๊ทธ๋ฅ ๋จ์ํ Main.java๋ฅผ ์คํํ์ ๋๋ ๊ฐ์ ์ข ๋ฃ (^C)๋ฅผ ํ ๊ฒ์ ๋ณผ ์ ์๋ค.
๊ทธ๋ ๋ค๋ฉด, ์ฐ๋ฆฌ๋ ์ด๋ป๊ฒ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํ ๊น?
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class Main {
private static boolean isStop = false;
private static synchronized void requestStop() {
isStop = true;
}
private static synchronized boolean isStop() {
return isStop;
}
public static void main(String[] args) throws IOException, InterruptedException {
Thread thread = new Thread(() -> {
int count = 0;
while (!isStop()) {
count++;
}
});
thread.start();
TimeUnit.SECONDS.sleep(1);
requestStop();
}
}
synchronized ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์๊ณผ ๊ฐ์ด ์์ ํ์๋ค.
ํ์ฌ isStop์ ํ๋๋ฅผ ์ ๋ฐ์ดํธํ๋ ๋ฉ์๋ (requestStop)์ ํ๋๋ฅผ ์ฝ์ด์ค๋ ๋ฉ์๋ (isStop) ๋ชจ๋๋ฅผ ๋๊ธฐํํ์๋ค.
ํํ๋ค ์ฐ๊ธฐ ๋๊ธฐํ๋ง ์งํํ๋ฉด ๋๋ ๊ฒ ์๋๋๊ณ ์๊ฐํ ์ ์๊ฒ ์ง๋ง, ๋ ๊ฐ์ง ๋ชจ๋ ๋๊ธฐํ๊ฐ ๋์ด์ผ ํ๋ค. (๋ผ๊ณ ์ฑ ์์ ๋งํ๋ค.)
๐ค ๊ทธ๋ฐ๋ฐ, ์ค์ ๋ก ์คํํด๋ณด์์ ๋ ์ฐ๊ธฐ ๋๊ธฐํ๋ง ํ์ ๊ฒฝ์ฐ๋ ์คํ์ด ์ข ๋ฃ๋์ง ์์์ง๋ง, ์ฝ๊ธฐ ๋๊ธฐํ๋ง ํ์ ๋๋ ์คํ์ด ์ข ๋ฃ๋์๋ค. ์ด์ ์ ๋ํด์ ์๊ฐํด๋ณด์๋ค. ์๋๋ ํ์์ ์๊ฐ์ด๊ธฐ ๋๋ฌธ์ ์ฝ์ง ์์๋ ๋๋ค.
์ฝ๊ธฐ๋ง ๋๊ธฐํ๋ฅผ ํ์ ๊ฒฝ์ฐ ๋ณ์๋ฅผ ์ฝ๋ ๋์ค์๋ ๋ฝ์ ๊ฑธ์๊ธฐ ๋๋ฌธ์, Main ์ค๋ ๋๊ฐ ์ข ๋ฃ๋๋ฉฐ ๊ฐ์ ๋ณ๊ฒฝํ ๋ค, ํด๋น ๊ฐ์ด true์ธ ์ํ๋ก ๊ณ์ ๋ฐ์์ฌ ์๋ฐ์ ์์ผ๋๊น (์ธ๋ถ์์ ๋ณ๊ฒฝํ ์๊ฐ ์์) ์ข ๋ฃ๋๋ ๊ฒ ์๋๊น ์ถ๋ค. (=ํญ์ ์ต์ ๊ฐ์ ๋ฐํํ๋ค)
๋ฐ๋ฉด์ ์ฐ๊ธฐ๋ง ๋๊ธฐํ๋ฅผ ํ๋ค๋ฉด, Main ์ค๋ ๋๊ฐ ์ข ๋ฃํ๊ธฐ ์ ์ ๊ฐ์ ๋ณ๊ฒฝํ๋ ๊ฒ๊น์ง๋ ์์์ ์ด์ง๋ง, ๊ฐ์ ์ฝ์ด์ค๋ ์ค๋ ๋๋ ๋ฝ์ด ์์ด ๊ทธ๋ฅ ์คํ๋๋ค. ์ด๋ฌ๋ฉด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ Main ์ค๋ ๋์, isStop()์ ํธ์ถํ๋ ์ค๋ ๋์ ๋ํด์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ด์ ์ผ๊ด์ฑ์ด ๋ง์ง ์๊ฒ ๋ ์ ์๋ค. ์ผ๊ด์ฑ์ด ๊นจ์ง๊ธฐ ๋๋ฌธ์ ์ ๋๋ก ๋ ๊ฒฐ๊ณผ๊ฐ์ ์ฝ์ด์ค์ง ๋ชปํ๊ณ ์ด๋ ํ ์ฐ๋ ๊ธฐ๊ฐ์ ์ฝ์ด์ค๋ฉด์ ์ข ๋ฃ๊ฐ ์ ๋๋ ๊ฒ์ด ์๋๊น... ๋ผ๋ ๊ฒ ๋์ ์๊ฐ์ด๋ค.
์ด๋ ํ ์ด์ ๋ , ๋ ๋ฉ์๋ ๋ชจ๋์ synchronized ํค์๋๋ฅผ ๋ถ์ฌ์ผ ๋์ฑ ์์ ํ๊ฒ ์คํ๋๋ ๊ฒ์ ํ์คํ๋ค.
์ฌ๋งํ๋ฉด ์ฝ๊ธฐ์ ์ฐ๊ธฐ ๋ชจ๋ ํค์๋๋ฅผ ๋ถ์ฌ์ ์์์ฑ์ ๋ณด์ฅํ๋๋ก ํ์.
๐ฌ synchronized ํค์๋์ ์๋ฆฌ
์ฐ์ , ์๋ฐ์์ ๋ชจ๋ ๊ฐ์ฒด๋ค์ ‘Monitor’๋ผ๋ ๊ฒ์ ๊ฐ์ง๋ฉฐ, ์ฌ๋ฌ ์ค๋ ๋๊ฐ ํด๋น ๊ฐ์ฒด๋ก ๋์์ ์ ๊ทผํ๋ ๊ฒ์ ๋ง๊ฒ ํ๋ค. ์๋ํ๋ฉด, ๊ฐ์ฒด๋ Heap ์์ญ์ ์ ์ฅ๋๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ์ค๋ ๋๊ฐ ๊ณตํต์ ์ผ๋ก ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์ฌ๊ธฐ์ monitor๋, ์ค๋ ๋ ๋๊ธฐํ๋ฅผ ์ํ ์ฌ๋ฌ ๋ฐฉ๋ฒ ์ค 'critical section (์๊ณ ์์ญ)'์ ๋ํด ๋๊ธฐํ๋ฅผ ์ ๊ณตํ๋ ์ผ์ข ์ ๋งค์ปค๋์ฆ์ด๋ค. ์๊ณ ์์ญ์ ๊ณต์ ๋ ์์์ ๋ํด์ ๋จ ํ๋์ ์ค๋ ๋๋ง ์ ๊ทผํ๋๋ก ํ๋ ๊ฒ์ด๋ฉฐ, ์ด๋ ํ๋์ ํ๋ก์ธ์ค์ ์ํ ์ค๋ ๋๋ง ์ ๊ทผ์ด ๊ฐ๋ฅํ๊ฒ ๋๋ค. (๋ค์ค ํ๋ก์ธ์ค์ ์ํ ์ค๋ ๋๋ X)
Each object in Java is associated with a monitor, which a thread can lock or unlock. Only one thread at a time may hold a lock on a monitor. Any other threads attempting to lock that monitor are blocked until they can obtain a lock on that monitor. A thread t may lock a particular monitor multiple times; each unlock reverses the effect of one lock operation.
๊ทธ๋ฆฌ๊ณ , synchronized๋ ์ด๋ฌํ critical section์ ๋ํด์ ์ค์ ํด์ฃผ๋ ๊ฒ์ด๋ค!
synchronized๋ฅผ ํตํด ์๊ณ ์์ญ์ ๋ํด ์ ์ธ์ ํด์ฃผ๊ณ , ํด๋น ์๊ณ ์์ญ์ ๋ํด ๋ชจ๋ํฐ ๋ฝ์ ์ป์ ์ ์์ผ๋ฉฐ,
์ด๋ ๊ฒ ์ป์ ๋ชจ๋ํฐ ๋ฝ์ ํด๋น ์๊ณ ์์ญ์ ์ฌ์ฉํ๋ ๋์ ๋ค๋ฅธ ์ค๋ ๋์์ ์ ๊ทผํ์ง ๋ชปํ๋๋ก ๋ง๊ฒ ๋๋ค!
monitor๋ฅผ ๊ฐ์ง๋ ๊ฒ์ monitorenter, ๋๋ ๊ฒ์ monitorexit์ด๋ผ๊ณ ํ๋ค.
monitorenter๋ฅผ ํตํด ๊ฐ์ฒด์ ๋ํ ๋ฝ์ ํ๋ํ๊ณ , ๋ค๋ฅธ ์ค๋ ๋์์ ํด๋น ๊ฐ์ฒด์ ๋ชจ๋ํฐ๋ฅผ ํ๋ํ๊ธฐ ์ ๊น์ง๋ ์ค๋ ๋๋ฅผ block ์ํ๋ก ์ ์งํ๋ค. ๋์ ๊ณผ์ ์ ๊ฐ๋จํ๊ฒ ์ดํด๋ณด์๋ฉด ์๋์ ๊ฐ๋ค.
1. synchronized ๋ธ๋ก์ด ์์๋๋ฉด, JVM์ ํด๋น ๊ฐ์ฒด์ ๋ํ ๋ฝ์ ํ๋ํ๋ค. (monitorenter)
2. synchronized ๋ธ๋ก์์ ์คํ๋๋ ๋ชจ๋ ์ฝ๋๋, ํด๋น ๊ฐ์ฒด์ ๋ฝ์ ๊ฐ์ง๊ณ ์คํ๋๋ค.
3. ๋ค๋ฅธ ์ค๋ ๋์์ ํด๋น ๊ฐ์ฒด์ ๋ฝ์ ํ๋ํ๋ ค๊ณ ํ ๋, ํด๋น ์ค๋ ๋๋ ๋ฝ์ ํ๋ํ๊ธฐ ์ ๊น์ง block ์ํ๋ก ์ ์ง๋๋ค.
4. synchronized ๋ธ๋ก์ด ์คํ ์๋ฃ๋๋ฉด, JVM์ ํด๋น ๊ฐ์ฒด์ ๋ํ ๋ฝ์ ํด์ ํ๋ค. (monitorexit)
๊ฒฐ๊ณผ์ ์ผ๋ก ๋ฝ์ ํ์ฉํ์ฌ ํ ๋ฒ์ ํ๋์ ์ค๋ ๋๋ง ์ ๊ทผํ๋๋ก ๋ง๋ ๋ค๊ณ ์ดํดํ๋ฉด ๋๋ค!
์์ง ๊ฐ๋ ์ด ์๋ฒฝํ๊ฒ ์ต๋๋ ๋๋์ ์๋์ง๋ง... ์ถ๊ฐ์ ์ผ๋ก ๊ด๋ จํด์ ๋ ๊ธ์ ์์ฑํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค...! ๐โ๏ธ