์น ์๋ฒ๋ฅผ ๊ฐ๋ฐํ ๋ ๋ณ๋ ฌ ํ๋ก๊ทธ๋๋ฐ์ ๋ํ ์ดํด๋ ์ค์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
Thread Safety๊ฐ ๋ณด์ฅ๋์ง ์๋ ์ํฉ์ ๊ฐ๋ฐ์์ ๊ณจ์น๋ฅผ ์ํ๊ฒ ํฉ๋๋ค.
์ด๋ ๋๋ ์ ์์ ์ผ๋ก ๋์ํ๋ ๊ฒ ๊ฐ๋ค๊ฐ๋, ํ์ด๋ฐ์ ๋ฐ๋ผ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค.
์ด๋ฌํ ๋ฒ๊ทธ๋ ์ํฉ์ ๋ฐ๋ผ ์ฌํ๋ ์๋, ์๋ ์๋ ์์ด์ ๋๋ฒ๊น ํ๊ธฐ๊ฐ ๋ฌด์ฒ ๊น๋ค๋กญ์ต๋๋ค.
์ค์ค๋ก๋ ์ธ์งํ์ง ๋ชปํ ๋ฒ๊ทธ๋ฅผ ๋ง๋ค์ง ์๊ธฐ ์ํด์ Thread Safety์ ๋ํด ์กฐ์ฌํด๋ด ๋๋ค.
๋ฐ์์ ๋ถ๋ค์ ๋ง์ง๋ง ์ ๋ฆฌ ๋ถ๋ถ์ ๋ณด์๋ฉด ๋๊ฒ ์ต๋๋ค.
๐ Thread Safety์ ์ ์์ ๋ํด์ ์์๋ด ๋๋ค.
๐ ๊ฐ๋จํ๊ฒ JVM Runtime Data Aread์ ๊ณต์ ์์์ ๋ํด์ ์์๋ด ๋๋ค.
๐ ๋จ์ผ์ฐ์ฐ๊ณผ ๋ณตํฉ์ฐ์ฐ์ ๋ํด์ ์์๋ด ๋๋ค.
๐ ๊ฒฝ์์กฐ๊ฑด์ ๋ํด์ ์์๋ด ๋๋ค.
๐ Thread Unsafetyํ ์ํฉ์ ์ดํด๋ณด๊ณ ๊ณ ์ณ๋ด ๋๋ค.
์๋ฐ๋ Multi Thread Progamming Language์ ๋๋ค.
Multi Threading๋ฅผ ๊ฐ๋จํ๊ฒ ๋งํ์๋ฉด โ์ฌ๋ฌ Thread๊ฐ ํ Process์ ์์์ ๊ณต์ ํ๋ฉฐ ๋์ํ๋ ๊ฒโ ์ผ๋ก ๋ณผ ์ ์์ต๋๋ค.
์ฆ, ํ ํ๋ก์ธ์ค๊ฐ ๋์์ ์ฌ๋ฌ ์ผ์ ํ ์ ์๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
์ฌ๊ธฐ์ ๋์๋ผ๋ ์๋ฏธ๋ ํ๊ณ ๋ค ์๋ก ๋ณต์กํด์ง ์ ์์ต๋๋ค. Single Core Processor์์๋ ์ค์ ๋ก ์ฌ๋ฌ ์ผ์ ์ฒ๋ฆฌํ ๊ฒฝ์ฐ ๋์์ ๊ทธ ์ผ์ ์ํํ๋ ๊ฒ์ด ์๋๋ผ, ์ฌ๋์ด ๋๋ผ์ง ๋ชปํ ์ ๋๋ก ๋น ๋ฅด๊ฒ ๋ฒ๊ฐ์๊ฐ๋ฉด์ ์ฒ๋ฆฌํ๋ ๊ฒ์ ๋งํฉ๋๋ค. ๋ฌผ๋ก Multi Core Processor์์๋ ์ค์ ๋ก ๋์์ Task๋ฅผ ์ํํ ์ ์์ต๋๋ค. ์ด์ ๋ํ ์์ธํ ๋ด์ฉ์ ๐ ๋์์ฑ๊ณผ ๋ณ๋ ฌ์ฑ์ ์ฐจ์ด ๐ ๋ฅผ ์ฐธ๊ณ ํ์๋ฉด ์ดํดํ๊ธฐ ์ข์ต๋๋ค.
Process์ ํ ๊ณต์ ์์์ ์ฌ๋ฌ Thread์์ ์ ๊ทผํ๋ฉด ๋์์ฑ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
Thread Safety๋ โProcess์ ํ ๊ณต์ ์์์ ์ฌ๋ฌ Thread๊ฐ ์ ๊ทผํ์ฌ ์ฐ์ฐ์ ํ ๋, ํญ์ ๊ทธ ์ฐ์ฐ๊ฒฐ๊ณผ์ ๊ธฐ๋๊ฐ์ด ์ผ๊ด์ฑ์ ๊ฐ์ง์ ๋ณด์ฅํ๋ ๊ฒโ์ ์๋ฏธํฉ๋๋ค.
์์ ์ฝ๋๋ก ์ดํด๋ณด๊ฒ ์ต๋๋ค.
@ThreadSafe
public class Calculator{
public int plus(int a, int b){
return a + b;
}
}
JVM์ Heap Area์ Method Area๋ ๋ชจ๋ Thread์์ ์ ๊ทผํ ์ ์์ต๋๋ค.
JVM์ Runtime Data Area์ ๋ํ ์ค๋ช ์ด ํ์ํ์ ๊ฒฝ์ฐ ๐ ํด๋น ์ํฐํด ๐์ ์ฐธ๊ณ ํด์ฃผ์๊ธฐ ๋ฐ๋๋๋ค.
์ด๋ ๊ฒ ๋ชจ๋ Thread์์ ์ ๊ทผํ ์ ์๋ ๊ณต์ ์์์ ๊ฒฝ์์กฐ๊ฑด์ ๊ฐ์ง๊ฒ ๋ฉ๋๋ค.
๊ฒฝ์์กฐ๊ฑด์ ์ฝ๊ฒ ๋งํ์๋ฉด "ํ์ด๋ฐ์ด ์ข์ง ์์ ๋ ๊ฒฐ๊ณผ๊ฐ ์๋ชป๋ ๊ฐ๋ฅ์ฑ"์ด๋ผ ๋ณผ ์ ์๊ฒ ์ต๋๋ค.
์ญ์ ๋ฐฑ๋ฌธ์ด๋ถ์ฌ์ผ๊ฒฌ ์ ๋๋ค.
public class ChattingRoom{
private int count = 0;
public void enter(){
count++; // ์ฑํ
๋ฐฉ์ ๋ค์ด์ค๋ฉด ์ฐธ๊ฐ ์ธ์์ ์ฆ๊ฐ์ํจ๋ค.
}
public long getCount(){
return count;
}
public static void main(String[] args) throws InterruptedException {
System.out.println("start");
final ChattingRoom chattingRoom = new ChattingRoom();
UserEntrance entrance = new UserEntrance(chattingRoom);
UserEntrance entrance2 = new UserEntrance(chattingRoom);
UserEntrance entrance3 = new UserEntrance(chattingRoom);
entrance.start();
entrance2.start();
entrance3.start();
Thread.sleep(10000);
System.out.println("์ฑํ
๋ฐฉ ์ธ์ ์ = " + chattingRoom.getCount());
System.out.println("end");
}
}
public class UserEntrance extends Thread{
private final ChattingRoom chattingRoom;
public UserEntrance(ChattingRoom chattingRoom) {
this.chattingRoom = chattingRoom;
}
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
chattingRoom.enter(); // ์ฆ๊ฐ!
}
}
}
/*
start
์ฑํ
๋ฐฉ ์ธ์ ์ = 20891
end
*/
์ฑํ ๋ฐฉ์ ์ ์ ๊ฐ ๋ค์ด์ค๋ฉด ์ฐธ์ฌ์ ์๋ฅผ ์ฆ๊ฐ์ํค๋ ํด๋์ค์ ๋๋ค.
ํฐ ๋ฌธ์ ๊ฐ ์์ด ๋ณด์ผ ์๋ ์์ง๋ง(...) ์ ์ฝ๋๋ ํ์ด๋ฐ์ ๋ฐ๋ผ์ ๋ฒ๊ทธ๋ฅผ ์ผ์ผํฌ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค. ๐ ๐ ๐
10,000๋ฒ ์ฉ 3๊ฐ์ Thread์์ ChattingRoom๊ฐ์ฒด์ count๋ฅผ ์ฆ๊ฐ์์ผฐ์ผ๋ ๊ฒฐ๊ณผ๋ 30,000์ด ๋์ฌ ๊ฒ์ด๋ผ ๊ธฐ๋ํ ๊ฒ์ ๋๋ค. ํ์ง๋ง ์๋ฑํ ๊ฒฐ๊ณผ๊ฐ ๋์์ต๋๋ค.
์ด๋ฐ ๊ฒฐ๊ณผ๊ฐ ๋์จ ์ด์ ๋ count๋ฅผ ์ฆ๊ฐ์ํค๋ ์ฐ์ฐ์ ํ์ด๋ฐ์ด ์ข์ง ์์๊ธฐ ๋๋ฌธ์ ๋๋ค.
[count++] ์ฐ์ฐ์ ๋จ์ผ์ฐ์ฐ์ผ๋ก ๋ณด์ด๊ฒ ์ง๋ง ์ฌ์ค ๋ณตํฉ์ฐ์ฐ์ ๋๋ค.
- [count++]์ ์๋ ์ฐ์ฐ๋ค์ ์กฐํฉ์ด๋ค.
- ์ฐ์ฐ 1 : count๋ก๋ถํฐ ๊ฐ์ ์ฝ์ด์จ๋ค.
- ์ฐ์ฐ 2 : ์ฝ์ด์จ ๊ฐ์ 1์ ๋ํ๋ค
- ์ฐ์ฐ 3 : ๋ํ ๊ฐ์ count์ ์ ์ฅํ๋ค.
- ์ต์ด์ count๋ 0์ด๋ค.
- Thread-1์ด ์ฐ์ฐ 1, ์ฐ์ฐ 2๋ฅผ ์ํํ๋ค. ๊ทธ๋ฆฌ๊ณ Context Switching ์ผ์ด๋๋ค.
๊ทธ ๋๋ฌธ์ ์ฐ์ฐ 3์ ์ํํ์ง ๋ชปํ๊ณ ์์ง count๋ 0์ด๋ค.
- Thread-2๊ฐ ์ฐ์ฐ 1์ ์ํํ๋ค ์ด ๋๊น์ง count์ ๊ฐ์ 0์ด๋ค.
๊ทธ๋ฆฌ๊ณ ์ฐ์ฐ 2~3์ ์ํํ๋ค. count์ ๊ฐ์ 1์ด ๋๋ค.
- ๋ค์ Context Switching ์ผ์ด๋๋ค.
์ด์ Thread-1์ด ์ฐ์ฐ 3์ ์ํํ๋ค. ์ฐ์ฐ 2๊น์ง์ ๊ฒฐ๊ณผ๋ 1์ด์๊ณ , ๊ทธ ๊ฐ์ count์ ๋ฃ๋๋ค.
- ๊ฒฐ๊ตญ ๋ ๋ฒ์ ์ฆ๊ฐ ์ฐ์ฐ์ด ์์์ง๋ง ๊ฒฐ๊ณผ์ ์ผ๋ก count์ ๊ฐ์ 1์ด๋๋ค.
์ฐ๋ฆฌ์ ๊ธฐ๋๊ฐ์ 2์์ผ๋ ์ข์ง ์์ ํ์ด๋ฐ ์ฆ, ๊ฒฝ์์กฐ๊ฑด์ ์ํด์ ๊ฒฐ๊ณผ ๊ฐ์ด 1์ผ ์๋, 2์ผ์๋ ์๋ ์ํฉ์ด ๋ฐ์ํ๋ค.
๋ฉ๋ชจ๋ฆฌ ๊ฐ์์ฑ์ "ํ Thread๊ฐ ๊ณต์ ์์์ ๋ณ๊ฒฝํ์ ๋ ๋ค๋ฅธ Thread์์๋ ๋ณ๊ฒฝ๋ ์ต์ ๊ฐ์ ์ฝ์ด์ฌ ์ ์๋๋"๋ฅผ ์๋ฏธํฉ๋๋ค.
์ด ๋ํ ์ฝ๋๋ก ์ดํด๋ณด๊ฒ ์ต๋๋ค.
public class NoVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread{
@Override
public void run() {
while (!ready) {
Thread.yield();
}
System.out.println("number = " + number);
}
}
public static void main(String[] args) {
new ReaderThread().start();
new ReaderThread().start();
new ReaderThread().start();
new ReaderThread().start();
number = 45;
ready = true;
}
}
๐ ์ฐธ์กฐ
๋ฉํฐ์ฝ์ด๋ฅผ 100% ํ์ฉํ๋ ์๋ฐ ๋ณ๋ ฌํ๋ก๊ทธ๋๋ฐ
Java Performance Fundamental
Guide to the Volatile Keyword in Java