๐ Java ๋ฉํฐ์ค๋ ๋ฉ, ๋ณํ์ฑ ๋ฐ ์ฑ๋ฅ ์ต์ ํ (์งํ์ค)
๊ธ๋ 9๊ธฐ & Udemy ์ง์์ ๋ฐ์ ๋ฃ๊ฒ ๋ ๊ฐ์ ๋ด์ฉ์ ์ ๋ฆฌํ ํ์ด์ง์ ๋๋ค.
1. ๊ฐ์
๋ฉํฐ์ค๋ ๋๋ ์๋ต์ฑ๊ณผ ์ฑ๋ฅ์ ์ํด ํ์ํฉ๋๋ค. ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์๋ ์๋ต์ ๋์์ ์ฒ๋ฆฌํ ์ ์๊ธฐ ๋๋ฌธ์ ๋์์์ด ์งํ์ค์๋ UI๋ก ๋ง์ฐ์ค๋ฅผ์์ง์ฌ ๋ค๋ฅธ ์์ ์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ์์ ์ด ๋์์ ์คํ๋๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋๋ฐ ์ฌ์ค์ Task์ ๋ฐ๋ฅธ ์ค๋ ๋๋ค์ ๋๋์ด ์ฒ๋ฆฌํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์ด๋ฐ ๋ณํ์ฑ์ด ๊ฐ๋ฅํฉ๋๋ค. ๋ฉํฐ ์ค๋ ๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋ง์ ์ฝ์ด๊ฐ ํ์ํ์ง ์์ต๋๋ค. ์ฑ๊ธ ์ค๋ ๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๋ณด๋ค ๋ง์ ์๋น์ค๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์ ๊ธฐ๊ณ ๋์๋ฅผ ์ค์ด๊ณ ํ๋์จ์ด ๋น์ฉ์ ์ ๊ฐํ ์ ์์ต๋๋ค.
์ด์์ฒด์ ๋ ํ๋ ๋์คํฌ์์ ๋ฉ๋ชจ๋ฆฌ๋ก ๋ก๋๋๊ณ ์ด์์ฒด์ ๋ ํ๋์จ์ด CPU ์ฌ์ด ์ํธ์์ฉ์ ๋์ต๋๋ค. ๊ฐ ์ ํ๋ฆฌ์ผ์ด์
๋ค์ ๋์คํฌ์์ ์คํ๊ณผ ๋์์ ์ด์์ฒด์ ์ ์ํด ํ๋ก๊ทธ๋จ์ ๋ฉ๋ชจ๋ฆฌ๋ก ๊ฐ์ง๊ณ ์์ ํ๋ก๊ทธ๋จ ์ธ์คํด์ค๋ฅผ ์์ฑํฉ๋๋ค.
๊ฐ ํ๋ก์ธ์ค๋ ๋
๋ฆฝ์ ์ด๋ฉฐ ๋ด๋ถ๋ PID, Code, Heap Data, Files, ๋ฉ์ธ ์ค๋ ๋๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ์ด ๋ ๋ฉ์ธ ์ค๋ ๋ ์ธ์ ๋ค๋ฅธ ์ค๋ ๋๋ฅผ ๊ฐ์ง๊ณ ์๋ค๋ฉด ๋ฉํฐ์ค๋ ๋๋ก ๋์ํ๋ ํ๋ก์ธ์ค์ธ ๊ฒ์ ์ ์ ์์ต๋๋ค. ์ค๋ ๋๋ ์คํ
์ ๊ฐ์ง๋๋ฐ ์ง์ญ๋ณ์๋ฅผ ๊ฐ์ง๊ณ ์๊ณ , instruction pointer
๋ฅผ ๊ฐ์ง๊ณ ์์ด
๋ค์ ๋ช
๋ น์ด ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๋ ์ญํ ์ ํฉ๋๋ค.
- ํ๋ก์ธ์ค์ ๊ตฌ์กฐ ์ถ๊ฐ์กฐ์ฌ
- ํจ์๋ฅผ ์คํํ๊ฒ ๋๋ฉด ํจ์๊ฐ ๋ฆฌํด๋ ์ฃผ์๊ฐ ์คํ ์ด ์ ์ฅ๋๊ณ ์ง์ญ ๋ณ์๋ค๋ ์ฐจ๋ก๋ก ์คํ์ ์์ด๋๋ฐ, ํจ์ ์คํ ํ์๋ ์คํ ๋ฐ์ดํฐ๋ค์ด ์ฐจ๋ก๋ก ์ฌ๋ผ์ง๊ณ ๋ฆฌํด๋ ์ฃผ์๋ ์ง์์ง๊ณ ๋ฆฌํด๋ ๊ณณ์ผ๋ก ์ด๋๋ฉ๋๋ค.
- ์คํ ํ๋ ์
- ํ๋ก์ธ์ค ์ํ์ ๊ณ์ธต๊ตฌ์กฐ
- ํ๋ก์ธ์ค์ ์ํ๋ฅผ PCB์ ๊ธฐ๋กํด์ ๊ด๋ฆฌ๋ฅผ ํฉ๋๋ค. ์๋ง์ ํ๋ก์ธ์ค๋ฅผ ๊ณ์ธต์ ์ผ๋ก ๊ด๋ฆฌ, ์ด์์ฒด์ ๋ง๋ค ํ๋ก์ธ์ค ์ํ๋ 5๊ฐ์ง๊ฐ ์๋ค. ์์ฑ, ์ค๋น, ์คํ, ๋๊ธฐ(blocked status), ์ข ๋ฃ ์ํ
- ๋ถ๋ชจ ํ๋ก์ธ์ค๋
fork
์์คํ ํธ์ถ๋ก ์์ ์ ๋ณต์ฌ๋ณธ ์์ ํ๋ก์ธ์ค๋ฅผ ์์ฑ, ์์ ์์ - ์์ ํ๋ก์ธ์ค๋
exec
๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์๋ก์ด ํ๋ก๊ทธ๋จ์ ๋ฎ์ด์ฐ๊ธฐ, ์ฝ๋/๋ฐ์ดํฐ ์์ญ์ ์คํํ ํ๋ก๊ทธ๋จ ๋ด์ฉ์ผ๋ก ๋ฐ๋๊ณ ๋๋จธ์ง ์์ญ์ ์ด๊ธฐํ
ํผ์ ๊ณต๋ถํ๋ ์ปดํจํฐ ๊ตฌ์กฐ ์ด์์ฒด์ ํ๋น ๋ฏธ๋์ด ๊ฐ์๋ฅผ ๋ค ๋ค์ด๋ณด๋ ๊ฒ๋ ์ข์ ๊ฒ ๊ฐ๋ค..!
์ปจํ ์คํธ ์ค์์น
๋์์ ๋ง์ ์ค๋ ๋๋ฅผ ๋ค๋ฃจ๋ ๊ฒ์ ์ฝ์ง ์๋ค. ๋ค๋ฅธ ์ค๋ ๋๋ก ์ ํํ ๋๋ ๊ธฐ์กด์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ๋ค๋ฅธ ์ค๋ ๋์ ๋ฆฌ์์ค๋ฅผ cpu์ ๋ณต์ํด์ผ ํฉ๋๋ค.
์ค๋ ๋ ์ค์ผ์ฅด๋ง
๊ธฐ์ํ์์ด ๋ฐ์๋ ์ ์๊ธฐ ๋๋ฌธ์ ์ด์์ฒด์ ๊ฐ cpu์ ์ค๋ ๋๋ฅผ ๊ณตํํ๊ฒ ๋ฐฐ์นํ ๋๋ ์ฌ๋ฌ ๋ฌธ์ ์ ๋ค์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค. ์ด์์ฒด์ ๋ ์ํฌํฌ์ ๋ง์ถฐ ์๊ฐ์ ์ ๋นํ ํฌ๊ธฐ๋ก ๋๋๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ค๋ ๋์ ํ์ ์ฌ๋ผ์ด์ค๋ฅผ ์ข
๋ฅ๋ณ๋ก ์ํฌํฌ์ ํ ๋นํฉ๋๋ค.
์ค๋ ๋์ ์๊ฐ์ ํ ๋นํ๋ ๋ฐฉ๋ฒ์ ์ด์์ฒด์ ๊ฐ ์ฐ์ ์์๋ฅผ ์ ํ๋ ๋ฐฉ๋ฒ์ ๋ฌ๋ ค์์ต๋๋ค. ์ธํฐ๋ ํฐ๋ธํ ์ค๋ ๋์ ์ฐ์ ์์๋ฅผ ๋๊ณ , ์ค๋ ๋ ์์ฒด๋ ์์ฑ๊ณผ ํ๊ดด๊ฐ ํจ์ฌ ์ฝ๊ณ ํ๋์ ํ๋ก์ธ์ค ์์์ ์ฌ๋ฌ ์ค๋ ๋๋ฅผ ์ฌ์ฉํด์ ๋ณํ์ฒ๋ฆฌ๋ฅผ ํ๋ฉด ๋ ๋น ๋ฅด๊ณ ํจ๊ณผ์ ์ผ๋ก ์ํํ ์ ์์ต๋๋ค.
๋ณด์๊ณผ ์์ ์ฑ์ ์ํด์๋ ํ๋์ ํ๋ก์ธ์ค์์ ์คํ๋๋ ๊ฒ์ด ์ข์ต๋๋ค.
2. ์ค๋ ๋ฉ ๊ธฐ์ด - ์ค๋ ๋ ์์ฑ
์ค๋ ๋ ๊ธฐ๋ฅ๊ณผ ๋๋ฒ๊น
Runnable
์ธํฐํ์ด์ค๋ฅผ ์ด์ฉํด์ ์ค๋ ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์ ์ค๋ ๋๋ฅผ ์ด์ฉํ๋ ๊ฒ ์ธ์๋ ์ด ์ค๋ ๋๊ฐ ์๋ค๋ ๊ฒ๋ง์ผ๋ก๋ ๋ฆฌ์์ค๋ฅผ ๊ณ์ ์๋นํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์ค๋ ๋๋ฅผ ๋ฐ๋ฅด๊ฒ ๊ด๋ฆฌํ๊ณ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฆฌ๋ฅผ ํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ํด์ ๊ณ ๋ฏผํด์ผ ํฉ๋๋ค.
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Runnable(){
@Override
public void run() {
Thread.currentThread().getName();
}
});
thread.setName("New Worker Thread");
thread.setPriority(Thread.MAX_PRIOPITY);
Thread.currentThread().getName();
thread.start();
Thread.currentThread().getName();
Thread.sleep(1000);
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Runnable(){
@Override
public void run() {
throw new RuntimeExcpetion("Intentional Exception");
}
});
thread.setName("Misbehaving thread");
thread.setUncaughtExceptionHandler(new Thread.UncaughtExcpetionHandler() {
@Override
public void uncaughtException(Thread t, Throuable e) {
t.getName();
e.getMessage();
}
})
}
์ค๋ ๋ ์์
public static void main(String[] args) throws InterruptedException {
Thread thread = new NewThread();
thread.start();
}
private static class NewThread extends Thread {
@Override
public void run() {
Thread.currentThread().getName();
}
}
Quiz
ํ๋์ ํ๋ก์ธ์ค์ ์ํ ๋ค์์ ์ค๋ ๋๋ ๋ค์ ํญ๋ชฉ์ ๊ณต์ ํฉ๋๋ค.
- ํ
- ์ฝ๋
- ํ๋ก์ธ์ค์ ์ด๋ฆฐ ํ์ผ
- ํ๋ก์ธ์ค์ ๋ฉํ ๋ฐ์ดํฐ
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Executing from a new thread");
}
});
์ด ์ฝ๋์๋ ์ค๋ ๋๋ฅผ ์์ฑํ๊ณ thread.start()
ํธ์ถ์ ํตํด ์์๋ ๊ฒฝ์ฐ, ์ ์ค๋ ๋์ run()
๋ฉ์๋ ์์ ์๋ ์ฝ๋๋ฅผ ์คํํ๊ฒ ๋ฉ๋๋ค.
์ฝ๋ฉ ์ฐ์ต 1: ์ค๋ ๋ ์์ฑ - MultiExecutor
import java.util.*;
public class MultiExecutor {
public MultiExecutor(List<Runnable> tasks) {
for(Runnable thread:tasks){
thread.run();
}
}
public void executeAll() {
Thread thread1 = new Thread("thread1");
Thread thread2 = new Thread("thread2");
List<Runnable> list = new ArrayList();
list.add(thread1);
list.add(thread2);
new MultiExecutor(list);
}
}
์ฝ๋ฉ ์ฐ์ต 2: ์ค๋ ๋ ์์ฑ - MultiExecutor ์๋ฃจ์
import java.util.ArrayList;
import java.util.List;
public class MultiExecutor {
private final List<Runnable> tasks;
/*
* @param tasks to executed concurrently
*/
public MultiExecutor(List<Runnable> tasks) {
this.tasks = tasks;
}
/**
* Executes all the tasks concurrently
*/
public void executeAll() {
List<Thread> threads = new ArrayList<>(tasks.size());
for (Runnable task : tasks) {
Thread thread = new Thread(task);
threads.add(thread);
}
for(Thread thread : threads) {
thread.start();
}
}
}
- ์ ๊ฐ ์์ฑํ ์ฝ๋์ ๋น๊ตํ์ ๋ ์๋ฃจ์
์ด ๋ ์ข๋ค๊ณ ๋๋ ์ ์ด ๋ง์๋๋ฐ, ์ผ๋จ ํด๋์ค์์ ํด๋น ํด๋์ค์ ์์ฑ์ ํธ์ถ์ ๊ทธ ํด๋์ค ๋ด์ ๋ฉ์๋์์
new MultiExecutor(list);
์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ํํํ๋๊ฒ ๋ถ์ ์ ํ ๊ฒ ๊ฐ์์ต๋๋ค. - ์๋ฃจ์
์์์ ํด๋ต์ฒ๋ผ
private final List<Runnable> tasks;
ํด๋์ค ๋ด ๋ณ๋ ์ง์ญ ๋ณ์๋ฅผ ๋๊ณ ๊ทธ ๋ณ์๋ฅผ ํ์ฉํด์ ๋ฉ์๋๋ฅผ ๋ง๋๋ ๊ฒ์ด ์ข์ ๊ฒ ๊ฐ๋ค๊ณ ์๊ฐํฉ๋๋ค.
3. ์ค๋ ๋ ์กฐ์
์ค๋ ๋๋ฅผ ์กฐ์ ํ๊ธฐ ์ํด Thread.interrupt();
๋ฅผ ์ด์ฉํ ์ฒ๋ฆฌ๋ฅผ ๋งํด์ฃผ๊ณ ์์ต๋๋ค. ํ์ง๋ง ์ด๊ฒ๋ง ๊ฐ์ง๊ณ ์ด ์ค๋ ๋๋ฅผ ์กฐ์ ํ ์ํํ ๋ฐฉ๋ฒ์ด ์๋ค๋ฉด ์ค๋ ๋๋ฅผ ๋ฉ์ถ์ง ๋ชปํ ์๋ ์์ต๋๋ค. Thread.currentThread().isInterrupted()
๋ก ์ค๋ ๋๋ง๋ค interrupt ์ฌ๋ถ๋ฅผ ํ์ธํด์ ์ฒดํนํ ์ ์์ ๊ฒ์
๋๋ค.
ํ์ง๋ง ์ด๋ ๊ฒ ๊ฐ๋ณ ์ฒดํนํ๋ ๋ฐฉ์๋ง๊ณ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์์๊น์? Daemon Thread๋ ์ ํ๋ฆฌ์ผ์ด์
์ข
๋ฃ(๋ฉ์ธ์ค๋ ๋์ ์ข
๋ฃ)์๋ ๋ถ๊ตฌํ๊ณ ๋์ํ๊ฒ ์ฒ๋ฆฌํ๊ฒ ํ ์ ์๋ ์ค๋ ๋์
๋๋ค. thread.setDaemon(true);
์ ๊ฐ์ ๋ฐฉ์์ผ๋ก Daemon Thread์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก๋ ๋ชจ๋ ์ค๋ ๋๊ฐ ์ํ๋ ํ ๋ฉ์ธ์ค๋ ๋๊ฐ ์์ ํ๊ฒ ์ข
๋ฃ๋ ์ ์๋๋ก Thread.join()
์ ์ด์ฉํ ์ค๋ ๋ ๋ณ๋ ฌ์ฒ๋ฆฌ ๋ฐฉ๋ฒ์ ์๊ฐํด ๋ณผ ์ ์์ต๋๋ค.
// ์ค๋ ๋๊ฐ interrupt๋ ๊ฒฝ์ฐ InterruptedException ์ฌ๋ก
@Override
public void run() {
try {
Thread.sleep(500000);
} catch (InterruptedException e) {
System.out.println("Existing blocking thread");
}
}
// ์ค๋ ๋์ interrupt ์ฌ๋ถ๋ฅผ checking ๋ฐฉ์
for (BigInteger i = BigInteger.ZERO; i.compareTo(power) != 0; i = i.add(BigInteger.ONE)) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("Prematurely interrupted computation");
return BigInteger.ZERO;
}
result = result.multiply(base);
}
// Daemon Thread์ ์ ์ฉ
thread.setDaemon(true);
4. ์ฑ๋ฅ ์ต์ ํ
์ฌ๊ธฐ์ ๋งํ๋ ์ฑ๋ฅ์ Latency
์ง์ฐ์๊ฐ๊ณผ Throughput
์ฒ๋ฆฌ๋์ผ๋ก ๋๋ ์ ์์ต๋๋ค.
์ง์ฐ์๊ฐ
CPU 1์ฝ์ด ๋น ํ๋์ task๋ง์ ์ํํ ์ ์๋๋ก ๋ฐฐ์น๋์ด ์๊ณ ์ค๋ ๋ ์๊ฐ ์ถ๊ฐ๋ ๊ฒฝ์ฐ(์ฆ ์ค๋ ๋ ์๊ฐ ๋ง์์ง ๊ฒฝ์ฐ), ์ผ๋ฐ์ ์ผ๋ก ์ปจํ
์คํธ ์ค์์นญ๊ณผ ์บ์ ์ฑ๋ฅ ์ ํ๋ก ์ด์ด์ง ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ต์ ์ ์ํ๋ ๋ชจ๋ ์ค๋ ๋๊ฐ Runnableํ ์ํ๋ผ๊ณ ๋งํ ์ ์์ต๋๋ค.
๊ฐ์์๋ ์ฌ๋ก๋ก thread๋ฅผ ์ด์ฉํ ์ง์ฐ์๊ฐ์ ์ค์ด๋ ์ด๋ฏธ์ง ํ๋ก์ธ์ฑ์ ๋ํ ๋ด์ฉ์ ๋ด๊ณ ์์๋๋ฐ, ๋ง ๋ณต์กํ์ง๋ ์์ง๋ง ์ด๋ฏธ์ง ๋ณํ๋ฅผ ์ค์ ๋ก ๋ณผ ์ ์์ด์ ํฅ๋ฏธ๋ก์ ์ต๋๋ค.
๋จผ์ RGB ์์ ๋ฝ์๋ด๊ธฐ ์ํด์๋ ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํ๋๋ฐ ๊ฐ ๋นํธ ์๋ฆฌ์ FF ์์น์ ๋ฐ๋ผ ํฝ์
์์ ์ธ์ฝ๋ฉ ๊ทธ๋ฃน ์ค ํ๋์ธ RGB ์์์ ๊ตฌํ ์ ์์ต๋๋ค. ์ฐธ๊ณ ๋ก ARGB๋ผ๊ณ ํํํ์ ๋๋ RGB ๋ฐฉ์์ ํ ๋ฒ์ ์ผ๋ก, ์ฌ๊ธฐ์ A๋ alpha, ์ฆ, ์ํ(ํฌ๋ช
๋)๋ฅผ ๋ปํฉ๋๋ค.
๋นํธ๋ง์คํฌ์ ๊ฒฐ๊ณผ๊ฐ์ ์๋ ๋ชจ๋ ๋นํธ๋ฅผ >>
์ฐ์ฐ์๋ฅผ ์ด์ฉํด ์ค๋ฅธ์ชฝ์ผ๋ก ์ํํธํด์ผ ํฉ๋๋ค.
public static int getRed(int rgb) {
return (rgb & 0x00FF0000) >> 16;
}
public static int getGreen(int rgb) {
return (rgb & 0x0000FF00) >> 8;
}
public static int getBlue(int rgb) {
return rgb & 0x000000FF;
}
๊ฐ์์์๋ ํฐ๊ฝ์ ๋ชจ๋ ๋ถํ์ ๊ฝ์ผ๋ก ๋ณํํ๋ ์ด๋ฏธ์ง ํ๋ก์ธ์ฑ ์์ ์ ์ฒ๋ฆฌํ๋๋ฐ, ๋ค์ ์ฝ๋์ ๊ฐ์ด ์ด๋ฏธ์ง ๋์ด๋ฅผ ์ค๋ ๋ ์๋ก ๋๋ ๊ฐ๊ฐ ์ค๋ ๋๊ฐ ์ฒ๋ฆฌํ ์ ์๋๋ก ํ์ต๋๋ค.
- ์ค๋ ๋ ์๋ฅผ ๊ฐ์ ์ฝ์ด ์๋ณด๋ค ๋ง๊ฒ ๋๋ฆฌ๋ฉด ๋ฒ ๋คํ์ด ์์ต๋๋ค.
- ์๊ณ ๋ฆฌ์ฆ์ ๋ณ๋ ฌ ์คํ์๋ ๋น์ฉ์ด ๋ง์ด ๋ญ๋๋ค.
public static void recolorImage(BufferedImage originalImage, BufferedImage resultImage, int leftCorner, int topCorner, int width, int height) { for(int x = leftCorner ; x < leftCorner + width && x < originalImage.getWidth() ; x++) { for(int y = topCorner ; y < topCorner + height && y < originalImage.getHeight() ; y++) { recolorPixel(originalImage, resultImage, x , y); } } }
์ฒ๋ฆฌ๋
์ฒ๋ฆฌ๋์ ์์ ๋์ ์ค๋ ๋๋ก ๋๋ ๊ฐ(T/N)์ ๋งํฉ๋๋ค. ์ฌ๊ธฐ์ Task๋ฅผ ๋๋๊ณ ํฉ์น๋ ๊ฒ๋ง์ผ๋ก ๋น์ฉ์ด ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ์์ ๋ณ๋ ์ค๋ ๋๋ฅผ ๋ง๋ค์ง ์๊ณ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ์คํ๋ ค ๋ ์ฑ๋ฅ์ด ์ข์ ์๋ ์์ต๋๋ค. ํ์ง๋ง ์ค๋ ๋ ์๊ฐ ๋ ๋ง์์ง๋ฉด ๊ทธ ์ฒ๋ฆฌ๋์์ ์ฒ๋ฆฌ๊ฐ ๋๊ธฐ ๋๋ฌธ์ ์ผ์ ์ ์ด์์ ์ค๋ ๋์์๋ ์ฑ๋ฅ์ด ๋ ์ข๊ฒ ๋์ค๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
5. ์ค๋ ๋ ๊ฐ ๋ฐ์ดํฐ ๊ณต์
์คํ๊ณผ ํ
์คํ์ ๋ฉ๋ชจ๋ฆฌ์์ ๋ฉ์๋๊ฐ ํ์ ์ ์ถ๋ก ์คํ๋๋ ๊ณต๊ฐ์ ๋งํฉ๋๋ค. ์คํ์๋ Local primitive types, Local references๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๋ฐ๋ฉด ํ์ JVM์์ ๊ด๋ฆฌํ๋ ๊ณต๊ฐ์ผ๋ก Objects, Class Members, Static valuables๋ฅผ ๋ด๋ ๊ณต๊ฐ์ ๋๋ค.
์์์ น ์์ , Atomic Operations
์์์ ์์
์ด๋ ๋ง๊ทธ๋๋ก ํ๋์ ์์์ ๊ฐ์ด ์์
์์ฒด๊ฐ ํ ๋ฒ์ ์คํ๋๋ ๊ฒฝ์ฐ๋ฅผ ๋งํฉ๋๋ค.
items++;
๋ ์์์ ์์
์ด๋ผ๊ณ ๋ณผ ์ ์๋๋ฐ ๊ทธ ์ด์ ๋ ๋ฉ๋ชจ๋ฆฌ์์ ํ์ฌ ๊ฐ์ ๊ฐ์ง๊ณ ์ค๊ณ , ๊ทธ ๋ค์ ๊ทธ ๊ฐ์ 1์ ๋ํ๊ณ , ๊ทธ new Value
๋ฅผ items
์ ๋์
ํ๋ ์์ผ๋ก ์งํ๋๊ธฐ ๋๋ฌธ์
๋๋ค.
6. ๋ณํ์ฑ ๋ฌธ์ ์ ์๋ฃจ์
์๊ณ์์ญ๊ณผ ๋๊ธฐํ
์๊ณ์์ญ์ด๋ ํ๋์ ์์์ฑ ์์
์ผ๋ก ์ฒ๋ฆฌํ ์ ์๊ฒ ํ๋ ์์ญ์ ๋งํฉ๋๋ค. ์ด ์์ญ์ด ํ๋์ ์์์ฑ ์์
์ผ๋ก ์ฒ๋ฆฌ๋ ์ ์๊ฒ ํ๊ธฐ ์ํด์ java์์๋ ๋ฉ์๋์ synchronized
์ฒ๋ฆฌ๋ฅผ ํด์ค๋๋ค. ๋๋ถ๋ถ ์์์ฑ ์์
์ get, sest, refercences์ ๊ฐ์ ์์
์ ์ฒ๋ฆฌํ ๋ ํด๋นํฉ๋๋ค. ํ์ง๋ง ๋๋ถ๋ถ์ ๋ฉ์๋๋ ๋น์์์ ์์
์ผ๋ก ๋์ด ์๊ธฐ ๋๋ฌธ์ ๋๊ธฐํ์ ๋ํด ๊ณ ๋ฏผํ ํ์๊ฐ ์์ต๋๋ค.
๋ณ์์๋ volatile
์ฒ๋ฆฌ๋ฅผ ํตํด ์์์ฑ์ ๋ถ์ฌํ ์ ์๋๋ฐ long
, double
๊ณผ ๊ฐ์ ๋ณ์๋ค์ 64bit ์๋ฐ์์ ๋ณด์ฅ๋์ง ์๊ธฐ ๋๋ฌธ์ 32bit๋ก ๋๋ ์ ์ฒ๋ฆฌ๋๋ ๊ณผ์ ์์ ์์์ฑ์ด ์ฌ๋ผ์ง๋๋ค.
private static class InventoryCounter {
private int items = 0;
Object lock = new Object();
public void increment() {
synchronized (this.lock) {
items++;
}
}
// ...
}
๊ฒฝ์ ์ํ ๋ฐ ๋ฐ์ดํฐ ๊ฒฝ์, ๋ฝํน ๊ธฐ๋ฒ๊ณผ ๋ฐ๋๋ฝ
๋ง ๊ทธ๋๋ก ๊ฒฝํฉ ์ํ์ ๋๊ธฐ์ฑ ๋ฌธ์ ๋ก ๋ฐ์ํ๋ ์ํฉ์ผ๋ก ๊ณต์ ๋ฆฌ์์ค์ ๋น์์์ ์ฐ์ฐ์ด ์คํ๋๊ธฐ ๋๋ฌธ์ ๋ฐ์ํฉ๋๋ค. ๊ฒฝ์์ํ ์ง์ ์ธ ์๊ณ์์ญ์ ๋๊ธฐํ ๋ธ๋ก์ ๋ฃ์ด ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค.
์ด๋ฐ ๊ฒฝ์์ํ์์ deadlock์ด ๋ฐ์ํ๊ฒ ๋๋๋ฐ ์ํธ๋ฐฐ์ , hold and wait, ๋น์ ์ , ์ํ๋๊ธฐ ๋ฌธ์ ๋ฅผ ๋ชจ๋ ๊ฐ์ง๊ณ ์๋ ๊ฒฝ์ฐ์ ๋ฐ์ํฉ๋๋ค. ์ํ๋๊ธฐ๋ฅผ ํผํ๊ธฐ ์ํด์ ์์๋๋ก ์คํ๋ ์ ์๋๋ก ๋ชจ๋ ๋ฉ์๋์ ์ ๊ทผ ์์๋ฅผ ์ ์งํ๋ ๋ฐฉ์์ ํด๊ฒฐ๋ฒ์ผ๋ก ์ ์ํ๊ณ ์์ต๋๋ค.
๋ฐ์ดํฐ ๊ฒฝ์์ ๋น์์ฐจ์ ์คํ์ผ๋ก ๋ฐ์ดํฐ๊ฐ ์์ฐจ์ ๊ณ์ฐ์ด ์๋ ๊ฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฐ์์ผ๋ก ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ๋งํฉ๋๋ค.
์๋ ์ฝ๋์์ increment()
์์ x++;
, y++;
๋ชจ๋ ์์์ ์์
์ด ์๋๊ธฐ ๋๋ฌธ์ ์ฒ๋ฆฌ ์ดํ์ checkForDataRace()
๋ฅผ ํ์ธํด๋ณด๋ฉด ๋ฐ์ดํฐ ๊ฒฝ์์ด ๋ฐ์ํ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
public class Main {
public static void main(String[] args) {
SharedClass sharedClass = new SharedClass();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
sharedClass.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
sharedClass.checkForDataRace();
}
});
thread1.start();
thread2.start();
}
public static class SharedClass {
private int x = 0;
private int y = 0;
public void increment() {
x++;
y++;
}
public void checkForDataRace() {
if (y > x) {
System.out.println("y > x - Data Race is detected");
}
}
}
}
7. ๋ฝํน ์ฌํ
ReentrantLock์ ์๋ฐ์์ ์ ๊ณตํ๋ ๊ฐ๋ ์ผ๋ก ๋ฝ์ ๊ณต์ ์ฑ์ ์ ์ดํ๋ ๋ฐฉ์์ ๋๋ค. ์ฃผ๋ก ์ฝ๊ธฐ ์์ ์ ํ๊ณ ์ฐ๊ธฐ ์์ ์ด ์ ์ ๊ฒฝ์ฐ์๋ ReentrantReadWriteLock์ ์ฌ์ฉํด์ ๊ณต์ ์์์ ๋์์ ์ฝ๋ ๊ฒ์ ํ์ฉํ๋ ๊ฒ์ด ๋ ํจ๊ณผ์ ์ ๋๋ค.
private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
private Lock readLock = reentrantReadWriteLock.readLock();
private Lock writeLock = reentrantReadWriteLock.writeLock();
public int getNumberOfItemsInPriceRange(int lowerBound, int upperBound) {
readLock.lock();
try {
Integer fromKey = priceToCountMap.ceilingKey(lowerBound);
Integer toKey = priceToCountMap.floorKey(upperBound);
if (fromKey == null || toKey == null) {
return 0;
}
NavigableMap<Integer, Integer> rangeOfPrices = priceToCountMap.subMap(fromKey, true, toKey, true);
int sum = 0;
for (int numberOfItemsForPrice : rangeOfPrices.values()) {
sum += numberOfItemsForPrice;
}
return sum;
} finally {
readLock.unlock();
}
}