Coding Planet
๊ฒฝ์์กฐ๊ฑด(Race Condition)๊ณผ Lock - ๊ฐ๋ ๊ณผ ์์ ํ๋ฒ์ ์ ๋ฆฌํ๊ธฐ ๋ณธ๋ฌธ
๊ฒฝ์์กฐ๊ฑด(Race Condition)๊ณผ Lock - ๊ฐ๋ ๊ณผ ์์ ํ๋ฒ์ ์ ๋ฆฌํ๊ธฐ
jhj.sharon 2024. 2. 29. 15:22ConCurrentHashMap๊ณผ HashTable์ ๊ณต๋ถํ๋ฉด์ ๊ฒฝ์์กฐ๊ฑด๊ณผ Lock์ด ์ฃผ์ ํค์๋๋ก ๋ฑ์ฅํ๋ค. ์ค๋ ๋๋ฅผ ๊ณต๋ถํ๋ฉด์ ๋น๋ฒํ๊ฒ ๋ฑ์ฅํ๊ธฐ ๋๋ฌธ์ ๋ ๊ฐ๋ ๋ชจ๋ ์ด๋ ดํ์ด ์๊ณ ์๊ธด ํ์ง๋ง ์ด๋ฒ ๊ธฐํ์ ์ ๋ฆฌํ๊ณ ๊ฐ์ผ๊ฒ ๋ค.
| ๊ฒฝ์ ์กฐ๊ฑด (Race Condition)๊ณผ Lock
๊ฒฝ์ ์กฐ๊ฑด์ ๋ฉํฐ ์ค๋ ๋ ํ๋ก๊ทธ๋จ์์ ๋ ๊ฐ ์ด์์ ์ค๋ ๋๊ฐ ๋ฐ์ดํฐ๋ ์์์ ๋์์ ์ ๊ทผํ๋ ค๊ณ ํ ๋ ๋ฐ์ํ๋ ๋ฌธ์ ์ด๋ค. ์ด๋ฌํ ์ํฉ์์ ์ค๋ ๋๋ค์ ์คํ ์์์ ๋ฐ๋ผ ํ๋ก๊ทธ๋จ์ ๊ฒฐ๊ณผ๊ฐ ๋ฌ๋ผ์ง ์ ์์ผ๋ฉฐ, ์ด๋ ๋ฐ์ดํฐ์ ์ผ๊ด์ฑ๊ณผ ์ ํ์ฑ์ ํด์น ์ ์๋ค. ๊ฒฝ์ ์กฐ๊ฑด์ ๋ฐฉ์งํ๊ธฐ ์ํด ๋๊ธฐํ ๋ฉ์ปค๋์ฆ(๋ํ์ ์ผ๋ก Lock)์ ์ฌ์ฉํ์ฌ ์ค๋ ๋๋ค์ด ์์์ ์์ ํ๊ฒ ์ ๊ทผํ ์ ์๋๋ก ํด์ผํ๋ค.
Lock์ ๋์์ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๊ฐ์ ์์์ ์ ๊ทผํ๋ ๊ฒ์ ๋ฐฉ์งํ๋ ๋๊ธฐํ ๋ฉ์ปค๋์ฆ์ด๋ค. ์๋ฐ์์๋ synchronized ํค์๋ ๋๋ Lock ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ Lock์ ๊ตฌํํ ์ ์๋ค. synchronized๋ ๋ฉ์๋๋ ์ฝ๋ ๋ธ๋ก ์ ์ฒด๋ฅผ ์๊ณ ์์ญ์ผ๋ก ์ ์ ํ๋ฉฐ, Lock ์ธํฐํ์ด์ค๋ ๋ ์ธ๋ฐํ ๋๊ธฐํ ์ ์ด๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ๋ค.
์์๋ฅผ ํตํ์ฌ ๋๊ธฐํ ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ ๋์ ์ฌ์ฉํ์ง ์์์ ๋๋ฅผ ๋น๊ตํ์ฌ ๊ฒฝ์์กฐ๊ฑด๊ณผ Lock์ ์ค๋ช ํ๋ ค๊ณ ํ๋ค.
| ex1. Lock์ ์ฌ์ฉํ์ง ์์์ ๊ฒฝ์ฐ
์๋ ์ฝ๋๋ ๋ ์ค๋ ๋๊ฐ ๊ฐ์ ์นด์ดํฐ ๊ฐ์ ๋์์ ์ฆ๊ฐ์ํค๋ ค๊ณ ํ ๋ ๊ฒฝ์์กฐ๊ฑด์ด ๋ฐ์ํ๋ ์ํฉ์ ๋ณด์ฌ์ค๋ค.
public class Counter {
private int count = 0;
public void increment() {
count++; // ์ฌ๊ธฐ์ lock์ด ์์
}
public int getCount() {
return count;
}
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Final count: " + counter.getCount()); // ์์ ๊ฒฐ๊ณผ๋ 2000์ด์ง๋ง, ๊ฒฝ์ ์กฐ๊ฑด์ผ๋ก ์ธํด ๋ค๋ฅธ ๊ฐ์ด ์ถ๋ ฅ๋ ์ ์์
}
}
์ค์ ์ธํ ๋ฆฌ์ ์ด์์ ์ฝ๋๋ฅผ ์คํํ ๊ฒฐ๊ณผ 1906์ด ๋์๋ค. increment() ๋ฉ์๋์ lock์ด ์๊ธฐ ๋๋ฌธ์ ๋ ์ค๋ ๋(t1, t2)๊ฐ count ๋ณ์๋ฅผ ๋์์ ์ฆ๊ฐ์ํค๋ คํ ๋ ์๋ก์ ์์ ์ ๋ฐฉํดํ ๊ฒ์ด๋ค.
์๋ฅผ ๋ค์ด, ํ ์ค๋ ๋๊ฐ count ๊ฐ(0)์ ์ฝ๊ณ ๊ฐ์ ์ฆ๊ฐ์ํค๊ธฐ ์ ์ ๋ค๋ฅธ ์ค๋ ๋๋ count(0)๋ฅผ ์ฝ์ด ์ฆ๊ฐ๊ฐ ํ๋ฒ๋ง ์ด๋ฃจ์ด ์ง ์ ์๋ค. ํ ์ค๋ ๋๊ฐ 0์ ์ฝ๊ณ -> 1๋ก ์ฆ๊ฐ -> ๋ค๋ฅธ ์ค๋ ๋๊ฐ 1์ ์ฝ๊ณ -> 2๋ก ์ฆ๊ฐ ์ด๋ฌํ ์ ์์ ์ธ ์ฆ๊ฐ๊ฐ ๋ํ๋์ง ์๊ณ ์ค๊ฐ์ ๊ผฌ์ธ๊ฒ์ด๋ค. ์ด๋ฌํ ๋ฌธ์ ๋๋ฌธ์ 2000์ด ๋์ค์ง ์์๋ค.
** ์๋ฐ์์ ์ค๋ ๋์ ์คํ ์์๋ ์ด์ ์ฒด์ ์ ์ค๋ ๋ ์ค์ผ์ค๋ฌ์ ์ํด ๊ฒฐ์ ๋๋ค. ์ค๋ ๋ ์ค์ผ์ค๋ฌ๋ ์ด์์ฒด์ ์ ์ผ๋ถ๋ก ๋ฉํฐ ํ์คํน์ ๊ฐ๋ฅํ๊ฒ ํ๊ธฐ ์ํด ์ด๋ค ์ค๋ ๋๋ฅผ ๋จผ์ ์คํํ ์ง ๊ฒฐ์ ํ๋ค. ์ค์ผ์ค์ ๊ฒฐ์ ํ๋ ๊ฒ์๋ ์ฌ๋ฌ ์กฐ๊ฑด์ด ์์ง๋ง ์ค์ ์ด์ ์ฒด์ ์ ์ค์ผ์ค๋ฌ๊ฐ ์ด ์กฐ๊ฑด์ ์ด๋ป๊ฒ ํด์ํ๊ณ ์ ์ฉํ ์ง๋ ๋ณด์ฅํ ์ ์๋ค.
| ex2. Lock์ ์ฌ์ฉํ ๊ฒฝ์ฐ
์๋ ์ฝ๋๋ ์ ์ฝ๋์ ๊ฒฝ์์กฐ๊ฑด์ ๋ฐฉ์งํ๊ธฐ ์ํด Lock์ ์ฌ์ฉํ ์ฝ๋์ด๋ค.
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Counter {
private int count = 0;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock(); // ๋ฝ์ ํ๋
try {
count++;
} finally {
lock.unlock(); // ๋ฝ์ ํด์
}
}
public int getCount() {
return count;
}
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Final count: " + counter.getCount()); // 2000์ด ์ ์์ ์ผ๋ก ์ถ๋ ฅ๋จ
}
}
์ฌ๋ฌ๋ฒ ์คํํ๋๋ฐ ๋ชจ๋ 2000์ด ์ถ๋ ฅ๋์๋ค. ์ด ์์์์ increment ๋ฉ์๋๋ ReentrantLock์ ์ฌ์ฉํ์ฌ ๋๊ธฐํ๋๋ค.
์ด๋ก ์ธํด, ํ ์์ ์ ํ๋์ ์ค๋ ๋๋ง์ด ์นด์ดํฐ ๊ฐ์ ์ฆ๊ฐ์ํฌ ์ ์์ผ๋ฉฐ, ๋ค๋ฅธ ์ค๋ ๋๋ ๋ฝ์ด ํด์ ๋ ๋๊น์ง ๋๊ธฐํด์ผ ํ๋ค. ์ด ๋ฐฉ์์ ํตํด ๊ฒฝ์ ์กฐ๊ฑด์ ๋ฐฉ์งํ๊ณ ํ๋ก๊ทธ๋จ์ ์ ํ์ฑ์ ๋ณด์ฅํ ์ ์๋ ๊ฒ์ด๋ค.
'๐ป Java Study > Java ์ด๋ก ์ ๋ฆฌ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๋ค์(Lamda expression) ์ด์ ๋ฆฌ์ ํ์ฉ์์ (0) | 2024.03.04 |
---|---|
[Java] ๋ฉ์๋์ ํจ์์ ์ฐจ์ด๋? (0) | 2024.03.04 |
HashMap / HashTable / ConCurrentHashMap ํ๋ฒ์ ์ ๋ฆฌํ๊ธฐ (1) | 2024.02.29 |
ThreadLocal๊ณผ ThreadLocalUtil (0) | 2024.02.28 |
๋ฐ๋ชฌ์ฐ๋ ๋(daemon thread) - ์ฌ์ฉํ๋ ์ด์ ์ java ์ฝ๋ ์ (0) | 2024.02.26 |