์๋ฐ์ ๋์์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋์๊ตฌ์กฐ (Atomic, Adder, Accumulator)
by JiwonDev์ด์ ๊ธ์์ ์๋ฐ์ Synchroized ํค์๋๋ ํ๊ณ๊ฐ ์์ผ๋, ๋์์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ผ๊ณ ํ์๋ค.
๐์ค๋ ๋์ Lock์ ๊ฑฐ๋ ์ด์
๋๊ธฐํ๋ฅผ ์ํด Lock์ ๊ฑฐ๋ ์ด์ ๋ฅผ ์กฐ๊ธ ๋ ๊น๋ํ๊ฒ ์ ๋ฆฌํด๋ณด์.
- Critical Section(์๊ณ์์ญ)์์ Mutual Exclusion(์ํธ ๋ฐฐ์ )๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด์์ด๋ค.
โก ์ฌ์ด๋ง๋ก [๊ณต์ ํ๋ ๋ฐ์ดํฐ์์ญ]์์ [ํ ์ค๋ ๋๋ง ์ ๊ทผํ ์ ์๋๋ก ํ์ฉ ๋ฐ ์ ํ]ํ๊ธฐ ์ํจ. - ์ค๋ ๋๊ฐ์ ํ์
๊ณผ ๋๊ธฐํ์ ์ญํ ์ ์ํํ๊ธฐ ์ํจ์ด๋ค.
โก ํน์ ์ํ์ ๋๋ฌํ ๊ฒฝ์ฐ, ๋ค๋ฅธ ์ค๋ ๋์๊ฒ ์๋ ค์ฃผ์ด ๋ค์ ์์ ์ ๋ฌธ์ ์์ด ํ ์ ์๊ฒ ์์ ์ ๋๊ธฐํํด์ค๋ค. - ๋ฐ์ดํฐ์ ๊ฐ์์ฑ (Visiblity)๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํจ์ด๋ค.
โก volatile ํค์๋์ฒ๋ผ ์บ์์๋ง ๋ฐ์ดํฐ๊ฐ ์์ด ๋ณ๊ฒฝ๋์์์๋ ๋ฐ์ดํฐ ๊ฐ์ด ๋๊ธฐํ ๋์ง ์๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ค.
๋ฑํ ์์๊ฐ ํ์ํ ์์ ์ด ์๋ ๊ฒ๋ ์๋๋ฐ [๊ณต์ ๋ฐ์ดํฐ์ ๊ฐ]์ ์ฝ๊ฑฐ๋ ์ ๋ฐ์ดํธํ ๋๋ง๋ค ์ด๋ ๊ฒ ์ค๋ ๋ Lock์ ๊ฑธ๊ฒ๋๋ค๋ฉด ์ฑ์ ์ฑ๋ฅ์ ํฌ๊ฒ ์ ํ๋๋ค.
๊ทธ๋์ Lock์ ๊ฑธ๊ธฐ๋ณด๋ค๋, ์์ ์ฐ์ฐ์ ์์์ฑ (Atomic)์ ๋ณด์ฅํ๋ ๋ณ์, ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ผ๊ณ ํ๋ค.
๐์์์ฑ์ ๋ณด์ฅํ๋ค์ ์๋ฏธ
์๋์ ํ ์ค ์ฝ๋๋ฅผ ๋ณด์. ํด๋น ์ฝ๋๋ ์์์ฑ์ ๋ณด์ฅํ๊ณ ์์๊น?
// ์๋์ ์ฝ๋๋ ์์์ฑ์ ๋ณด์ฅํ๋ ์์
์ผ๊น?
value = value + 1;
์ฝ๋๋ฅผ ๋จ ํ์ค๋ฐ์ ์์ฑํ์ง ์์๊ณ , ๋จ์ํ 1์ ๋ํ๊ณ ์๊ธฐ๋๋ฌธ์ ๋ณ ๋ฌธ์ ๊ฐ ์๋ค๊ณ ์๊ฐํ ์ ์๋ค.
ํ์ง๋ง ํด๋น ์ฝ๋๋ CPU์ ์ํด ์ฒ๋ฆฌ๋ ๋ ์๋์ ๊ฐ์ ์ฌ๋ฌ ์์ ์ ๊ฑฐ์น๊ฒ ๋๋ค.
LOAD - value์ ๊ฐ์ ๋ ์ง์คํฐ๋ก ๋ก๋ฉํจ.
ADD - ๋ ์ง์คํฐ์ ๊ฐ์ 1์ ๋ํจ
STORE - ๋ ์ง์คํฐ์ ๊ฐ์ value ๋ฉ๋ชจ๋ฆฌ๋ก ์ ์ฅํจ.
์ด 3๊ฐ์ ์ฐ์ฐ์ด [์ ๋ถ ์คํ๋์ง ์๊ฑฐ๋] or [ํญ์ ํจ๊ป ์คํ๋จ]์, ์ฆ ์์์ฑ์ ๋ณด์ฅํ๊ณ ์๋ค๊ณ ๋งํ ์ ์์๊น?
1. A ์ค๋ ๋๊ฐ ๊ฐ์ ๋ ์ง์คํฐ์ LOADํ๊ณ , ๋ํ๊ณ ์๋ ์์ค์
2. B ์ค๋ ๋๊ฐ ์ ๊ทผํด์ ๊ทธ ๊ฐ์ ์ฝ๊ณ ์์ ํ๊ณ STORE๋ก ์ ์ฅํ์๋ค.
3. ๊ทธ๋ฆฌ๊ณ A ์ค๋ ๋๊ฐ ๊ฐ์ ๋ค์ STOREํ๋ฉด ์ด๋ค ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊น?
์ฆ, value = value + 1; ์ฐ์ฐ์ ์์์ ์ผ๋ก ์คํ๋๋ ์ฐ์ฐ์ด ์๋๋ค. ์ฆ, ๊ฐ๊ฐ์ ์ฐ์ฐ ์ค๊ฐ์ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ๋ผ์ด๋ค์ด ๋ฉ๋ชจ๋ฆฌ ๊ฐ์ ๋ฎ์ด ์ฐ๊ฑฐ๋ ์์ ์ค์ธ ๋๋ฌ์ด ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ์ ์๋ค๋ ๋ง์ด๋ค.
๐ Atomic ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ด๋ป๊ฒ ์์์ฑ์ ๋ณด์ฅํ ๊น?
๊ทธ๋ ๋ค๋ฉด java.util.concurrent.atomic ์ ์ด๋ป๊ฒ ์์์ฑ์ ๋ณด์ฅํ๋ ๋ง์ ์ ํ๋๊ฑธ๊น?
import java.util.concurrent.atomic.AtomicInteger;
private AtomicInteger counter = new AtomicInteger();
public int getNextUniqueIndex() {
return counter.getAndIncrement();
}
AtomicInteger๋ฅผ ๋ฏ์ด๋ณด์. getAndIncrement()๋ ์๋์ ๊ฐ์ด ๋์ํ๋ค.
public long incrementAndGet() {
long oldValue;
long newValue;
do {
oldValue = value;
newValue = oldValue + 1;
} while (!compareAndSwap(value, oldValue, newValue));
return newValue;
}
ํํ ์ด๋ฐ ๋ฐฉ์์ CAS (Compare And Swap)์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค. Atomic ํด๋์ค๋ ๊ธฐ๋ณธ์ ์ผ๋ก CAS๋ก ๋์ํ๋ค.
๊ฐ์ ๋ณ๊ฒฝํ๊ธฐ ์ , ์ค๋ ๋์ ์คํ ๋ฉ๋ชจ๋ฆฌ(oldValue)์ ์ ์ฅํ๊ณ ๊ฐ์ ๊ณ์ฐํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ฐ์ฐ์ ์๋ฃํ ํ ํ์ฌ ์กด์ฌํ๋ ๊ฐ๊ณผ ์ ์ฅํด๋จ๋ oldValue๊ฐ ๊ฐ์ ๋๋ง ์์ ์ ์งํํ๊ณ , ๋ง์ฝ ๋ค๋ฅด๋ค๋ฉด ์ฐ์ฐ ์์ฒด๋ฅผ ์ทจ์ํ๊ณ ๋ค์ ์งํํ์ฌ ์ฐ์ฐ์ ์์์ฑ์ ๋ณด์ฅํ๋ ๋ฐฉ์์ด๋ค.
๋ฌผ๋ก CAS ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด Race Conditions, ์ค๋ ๋ ๊ฒฝํฉ์ด ์ฌํ๋ค๋ฉด CPU ์ฌ์ฉ๋ฅ ์ด ์ฆ๊ฐํ๊ฒ ์ง๋ง, ์ ์ด๋ Lock์ผ๋ก ํด๋น ์ค๋ ๋๋ฅผ ์๋ฌด๊ฒ๋ ๋ชปํ๊ฒ ์ ๊ถ๋ฒ๋ฆฌ๋ ๊ฒ ๋ณด๋ค๋ ์ฑ๋ฅ์ ์ธ ์ธก๋ฉด์์๋ ํจ์ฌ ์ข๋ค.
๋ํ Atomic์ JVM์์ ์ ๊ณตํ๋ Unsafe ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ค. ์ด๋ native ๋ฉ์๋๋ก ์ด๋ฃจ์ด์ ธ์๋๋ฐ ์๋ฐ์์ C/CPP ์ฒ๋ผ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ค๋ฅผ ์ ์๊ฒ ๋ง๋ ์ ์์ค ํฌ์ธํฐ๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค. ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ง์ ๋ค๋ฃจ๋ ๋งํผ ์ฑ๋ฅํฅ์์ด ๊ฐ๋ฅํ์ง๋ง ๊ทธ๋งํผ ์ํ์ฑ์ ๊ฐ์ง๊ธฐ ๋๋ฌธ์ ๋ฆฌํ๋ ์ ์ผ๋ก๋ง ์ฌ์ฉ ๊ฐ๋ฅํ๊ฒ ์์ฑ์์ ํฉํ ๋ฆฌ ๋ฉ์๋๊ฐ ๋งํ์๋ค.
๊ทธ๋์ ์ค์ ์ฝ๋๋ฅผ ์ดํด๋ณธ๋ค๋ฉด ์๋์ ๊ฐ์ด ๊ตฌ์ฑ๋์ด ์์์ ์ ์ ์๋ค.
public class AtomicInteger extends Number implements java.io.Serializable {
/*
* This class intended to be implemented using VarHandles, but there
* are unresolved cyclic startup dependencies.
*/
private static final Unsafe U = Unsafe.getUnsafe();
public final int incrementAndGet() {
return U.getAndAddInt(this, VALUE, 1) + 1;
}
}
๐ Atomic Adder์ Accumulator, ๊ฒฝํฉ์ ์ต์ํ
์์์ ์ค๋ช ํ๋๋ก ๋จ์ํ CAS๋ฅผ ๊ตฌํํ๋ค๋ฉด, ์ค๋ ๋์ Lock์ ๊ฑธ์ง ์๊ณ ๋ฉ๋ชจ๋ฆฌ์ ์์์ฑ์ ๋ณด์ฅํ ์ ์๋ค.
๊ฐ์ ์์ ํ์ง์๊ณ '์ฝ๊ธฐ'๋ง ๋ง์ด ํ๋ค๋ฉด ํน๋ณํ ๋์์์ด ๊ทธ๋๋ก ํจ์ฌ ์ฑ๋ฅ์ด ์ข์ ๊ฒ์ด๋ค.
ํ์ง๋ง ์์ ์ด ์์ฃผ ๋ฐ์ํ๋ค๋ฉด? ์ฆ ์ค๋ ๋๋ค์ด ์๋ก ์์น๋ฝ ๋ค์น๋ฝํ๋ฉฐ ์คํ / ๋กค๋ฐฑ์ ๋ฐ๋ณตํ๊ฒ ๋๋ฉฐ CPU์ ์ฌ์ฉ๋ฅ ์ด ์ฆ๊ฐํ๊ฒ ๋๋ค. ์ด๋ฐ ๊ฒฝ์ฐ์ ์ฌ์ฉํด๋ผ๊ณ Java Atomic์์๋ Adder์ Accumulator ์ธํฐํ์ด์ค๋ฅผ ๋ฐ๋ก ์ ๊ณตํด์ค๋ค.
AtomicLong์ผ๋ก ์๋ฅผ ๋ค๋ฉด LongAdder์ LongAccumulator๊ฐ ์กด์ฌํ๋ค. ์ด ๋ ํด๋์ค๋ API๋ง ์กฐ๊ธ ๋ค๋ฅผ ๋ฟ, ๋ด๋ถ ๊ตฌ์กฐ๋ ๋น์ทํ๋ค. CAS ์ฐ์ฐ์์ ๊ฒฝํฉ ๊ณผ์ ์ ์ํ CPU ์๋ชจ๋ฅผ ์ค์ด๊ธฐ ์ํด ๊ณ ์๋ ๋ฉ์๋๋ค์ด๋ค.
๊ฐ๋จํ ์ค๋ช ํ์๋ฉด, [๊ณต์ฉ ๋ฉ๋ชจ๋ฆฌ์ธ Base]์ [์ค๋ ๋ ๋ณ ๋ฉ๋ชจ๋ฆฌ์ธ Cell]๋ก ๋๋๋ค.
๊ทธ๋ฆฌ๊ณ Base ๋ณ์๋ฅผ CAS ๋ฐฉ์์ผ๋ก ์ฝ๋ค๊ฐ ๋ง์ฝ ์คํจํ๋ค๋ฉด while(...)๋ก ๋ฐ๋ณตํ๋๊ฒ ์๋๋ผ ์ค๋ ๋ ๋ณ๋ก Cell ๋ฉ๋ชจ๋ฆฌ์ ๋ณ๋์ ์ฐ์ฐ์ ์งํํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋์ ์ต์ข ์ ์ผ๋ก ๊ฐ ์ค๋ ๋์ ๊ฐ์ ํฉ์ณ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ ๋ฐฉ์์ด๋ค.
์ด๋ ๊ฒ ๋ฐ์ดํฐ๋ฅผ ๋ถ์ฐํด์ ์ ์ฅํ๋ ๋ฐฉ์์ ์คํธ๋ผ์ดํ(Striping)์ด๋ผ ํ๋ฉฐ ์ํฉ์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๋์์ด ๋ฌ๋ผ์ง๋ค๊ณ ํ์ฌ ์ด ๋ฐฉ์์ Dynamic Striping ์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
๐ ์ด์์ฒด์ ์ ์ดํด, CPU Cache์ False Sharing ์ต์ํ
์์ ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋ณด๋ฉด ์๊ฒ ์ง๋ง, Cell ์์ญ์ ์ผ๋ฐ์ ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ์์ ๊ทผ์ ํ ์ ๋ฐ์ ์๊ฒ๋๋ค.
์ด์์ฒด์ ๋ CPU cache๋ ์ง์ญ ์ฐธ์กฐ์ฑ์ ๋ฐํ์ผ๋ก ์ค๊ณ๋์ด์๋ค. ์ปดํจํฐ ํ๋ก๊ทธ๋จ์ ํน์ฑ์ ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ฌ์ ์ฝ์ ํ๋ฅ ์ด ๋์ผ๋ฏ๋ก ๋ค์ ๋ฐ์ดํฐ๋ฅผ CPU์ Cacheํด๋์ ์ฑ๋ฅ์ ๋์ธ๋ค.
์ฆ Cell ์์ญ์ Cpu Cache์ ํ ๋ผ์ธ์ ์์นํ ๊ฐ๋ฅ์ฑ์ด ๋๊ณ , ํ ์ค๋ ๋๊ฐ ์์ ์ Cell์ ๋ณ๊ฒฝํ ๊ฒฝ์ฐ ๊ฐ์ ๋ผ์ธ์ ์๋ ๋ค๋ฅธ ์ค๋ ๋์ Cpu Cache ์์ญ๋ ๊ณ์ ์ ๋ฐ์ดํธํ๊ฒ๋๋ค. ์ฆ ์ธ๋ ์์ด ์บ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ ํด ์ฑ๋ฅ์ด ๋๋น ์ง๋ False Sharing (๊ฑฐ์ง ๊ณต์ )๊ฐ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Atomic ์์๋ ์ด๋ Cell์ ํฌ๊ธฐ๊ฐ Cpu Cache Line์ ํฌ๊ธฐ์ ๊ฐ์์ง๋๋ก ๋น ๊ณต๊ฐ์ ๋ถ์ฌ Paddingํ๋๋ก ๋ง๋ ๋ค.
๐ ๊ทธ๋์ Atomic์ด Synchroized๋ณด๋ค ์ ์ข๋ค๊ตฌ์?
๋ค์ ๋ณธ๋ก ์ผ๋ก ๋์๊ฐ๋ณด์. Atomic์ ์ด๋ป๊ฒ ์์์ฑ์ ๋ณด์ฅํ๋ฉฐ, ์ ์ฑ๋ฅ์ด ์ข์ ๊ฒ์ผ๊น?
- CAS ๋ฐฉ์์ผ๋ก ์ค๋ ๋ Lock ์์ด ๋๊ธฐํ๋ฅผ ๋ณด์ฅํ๋ค.
- Unsafe๋ฅผ ์ด์ฉํ์ฌ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ์์ค์ผ๋ก ๋ค๋ค ์ฑ๋ฅ์ ์ต์ ํํ๋ค.
- ์ฐ๊ธฐ๊ฐ ๋ง์ด ๋ฐ์ํด์ ์ค๋ ๋ ๊ฒฝํฉ(Racing)์ด ์์ฃผ ๋ฐ์ํ๋ค๋ฉด, ํ์์๋ ๊ฐ์์ฑ ๋ณด์ฅ(volatile)์ด ์์ฃผ ๋ฐ์ํ๋ค.
- ์ด ๊ฒฝ์ฐ Atomic์ API๋ฅผ ์ฌ์ฉํ๋ฉด ๋ง์ ์ฑ๋ฅ ํฅ์์ ์ป์ ์ ์๋ค. ์ฝ๊ธฐ์๋ ๊ทธ๋ฅ ์ฌ์ฉํ๋ค๊ฐ Dynamic Striping ์ ํตํด ๊ฒฝํฉ์ด ๋ฐ์ํ๋ค๋ฉด ์ค๋ ๋ ๋ณ ๋ฉ๋ชจ๋ฆฌ(Cell)์ ๋ฐ๋ก ์ฐ์ฐํ ํ, ๋์ค์ ํฉ์น๋ ๋ฐฉ๋ฒ์ด๋ค.
- ๋ํ Cpu Cache์ False Sharing์ ์ต์ํํ๊ธฐ ์ํด Cpu Cache Line์ ํฌ๊ธฐ๋ก ํจ๋ฉ์ ๊ตฌํํ๋ค.
๐ ConcurrentHashmap์ Lock Striping
ConcurrentHashMap์ ์ด๋ป๊ฒ ์์์ฑ์ ๋ณด์ฅํ ๊น? ๊ฐ๋จํ ์์ ๋ฅผ ํตํด ์์๋ณด์.
๋จ์ํ ๋ฉ์๋์ synchroized๋ฅผ ์ฌ์ฉํด์ ๋๊ธฐํ๋ฅผ ํ๋ฉด ์๋์ ๊ฐ์ ๊ฒ์ด๋ค.
class SharedData {
private int intData;
private boolean boolData;
public synchronized int getInt() { return intData; }
public synchronized void setInt(int n) { intData = n; }
public synchronized boolean getBool() { return boolData; }
public synchronized void setBool(boolean b) { boolData = b; }
};
์ด๋ ๊ฒ ํ๋ค๋ฉด ๋ฑํ Lock์ ๊ฑธ ํ์๊ฐ ์์์๋ ์ค๋ ๋๊ฐ ๋ฉ์ถฐ๋ฒ๋ ค ์ฑ๋ฅํ ์๋นํ ๋๋น ์ง๋ค.
๊ทธ๋์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๋ ์ฝ๋๋ณ๋ก Lock์ ๊ฑฐ๋ ๊ฒ ์ฒ๋ผ ๊ฐ์ฒด๋ ๋ฐฐ์ด๋ฑ์ ์ด์ฉํด์ Lock์ ์ฌ๋ฌ๊ฐ๋ก ์ชผ๊ฐ ๋ค.
class SharedData {
private int intData;
private boolean boolData;
private Object intSync = new Object(); // ์ฐธ๊ณ ๋ก intData ์์ฒด๋ฅผ Lock์ผ๋ก ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ์ด ๊ตฌ๋ฆฌ๋ค.
private Object boolSync = new Object(); // ์ฝ๊ธฐ ๊ฐ์ ํ์์๋ ๋์์๋ Lock์ด ๊ฑธ๋ฆฌ๋๊น.
// intSync, boolSync ๋ก ๊ฐ๊ฐ ๋ค๋ฅธ Lock์ ๊ฐ์ง๋ฉฐ, ์ด ๋ ๊ฐ๋ ๋์์ ์คํ ๊ฐ๋ฅํ๋ค.
public int getInt() { synchronized (intSync) { return intData; } }
public void setInt(int n) { synchronized (intSync) { intData = n; } }
public boolean getBool() { synchornized (boolSync) { return boolData; } }
public void setBool(boolean b) { synchronized (boolSync) { boolData = b; } }
}
์ด๋ฅผ Lock์ ์ฌ๋ฌ๊ฐ๋ก ๋๋ด๋ค๋ Lock Splitting ๋ฐฉ์์ด๋ผ ๋ถ๋ฅธ๋ค. (* ์์ง ๋ถ์ฐ ์ ์ฅ์ ์๋ฏธํ๋ Striping ์ด ์๋๋ค.)
๐ SharedData๋ฅผ ๋ ๊ฐ์ ํ ๋ฐฉ๋ฒ์ด ๋ ์ค๋ฅด์ง ์๋๊ฐ?
์ฐ๋ฆฌ๊ฐ ์์์ ํ๋ ๋ฐฉ๋ฒ. Atomic ์๋ฃํ์ ์ฌ์ฉํ๋ฉด ๋๋ค. ๊ทธ๋ผ ๋ณต์กํ ์ฒ๋ฆฌ ์์ด Lock Striping(์คํธ๋ผ์ดํ)์ ์ฌ์ฉํ๊ฒ ๋๊ณ , ์ด๋ Lock์ ๊ฑธ์ง ์์ ์์ ๋ฐฉ์๋ณด๋ค ์ฑ๋ฅ์ด ํจ์ฌ ์ข๋ค.
class SharedData {
private AtomicInteger intData = new AtomicInteger(0);
private AtomicBoolean boolData = new AtomicBoolean(false);
public int getInt() { return intData.get(); }
public void setInt(int n) { intData.set(n); }
public boolean getBool() { return boolData.get(); }
public void setBool(boolean b) { boolData.set(b); }
}
์ค์ ConcurrentHashmap์ ์ฝ๋๋ฅผ ์ดํด๋ณด๋ฉด AtomicReference๋ฅผ ์ฌ์ฉํจ์ ์ ์ ์๋ค.
AtomicClass๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๋์์ ๋์ผํ์ง๋ง, AtomicReference๋ก ํ๋ฒ ๋ ๊ฐ์ผ ์ด์ ๋ HashMap ๊ตฌ์กฐ์ ๋ฉ๋ชจ๋ฆฌ ๋์์ ๊ด๋ จ์๋ค. ๊ถ๊ธํ๋ฉด WeakHashMap์ WeakReference ๋ํด ์ฐพ์๋ณด๋ฉด ์ดํดํ ์ ์์ ๊ฒ์ด๋ค.
public void atomicReference1() { // AtomicClass์ ์ฌ์ฉ๋ฒ์ ํฐ ์ฐจ์ด๋ ์๋ค.
AtomicReference<Integer> atomic = new AtomicReference<>();
System.out.println("atomic : " + atomic.get()); // atomic.get() == null
AtomicReference<Integer> atomic2 = new AtomicReference<>(10);
System.out.println("atomic2 : " + atomic2.get()); // atomic.get() == 10
}
๐ ConcurrentHashMap ์ ํจ์จ์ ์ธ ๋๊ธฐํ๋ฅผ ์ํ API
๊ทธ๋ฅ Map์ ์ฌ์ฉํ ๋์ ์ฝ๋๋ฅผ ์ดํด๋ณด์. ํด๋น ์ฝ๋๋ ์์์ฑ์ ๋ณด์ฅ ํ๋๊ฐ?
if (map.containsKey(key) == false) {
map.put(key, value);
} else {
doSomthing();
}
์๋๋ค. ๋น๊ต๋ฅผ ํ๋ ๋์๊ณผ put์ผ๋ก ์ฝ์ ํ๋ ๋์์ฌ์ด์ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์นจ๋ฒํ์ฌ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ค.
๊ทธ๋์ ConcurrentHashMap์ ์๋์ ๊ฐ์ ๋ฉ์๋๋ฅผ ์ ๊ณตํด์ค์ ํด๋น ๋์์ ์์์ฑ์ ๋ณด์ฅํด์ค๋ค.
// ์ฐธ๊ณ ๋ก putIfAbsent๋ ํด๋น ๊ฐ์ด ์๋ค๋ฉด ์ถ๊ฐํ๋ ๋ฉ์๋์ด๋ค.
// ๋ฐํ๊ฐ์ผ๋ก๋ ํ์ฌ Map์ ์
๋ฐ์ดํธ๋ ๊ฐ์ ๋ฐํํ๋ค. (์ฆ ์ด๋ฏธ ์๋ค๋ฉด ๊ธฐ์กด ๊ฐ์ ๋ฐํํจ.)
if (map.putIfAbsent(key, value) != value) {
doSomthing();
}
'๐๊ธฐ๋ณธ ์ง์ > Java ๊ธฐ๋ณธ์ง์' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์์์ ํ๋ฆ๋๋ก ์จ๋ณด๋ DB ํธ๋์ญ์ ์ด์ผ๊ธฐ (0) | 2022.08.15 |
---|---|
์๋ฐ์ NIO (java.nio) (1) | 2022.03.08 |
์ค๋ธ์ ํธ ๋์์ธ ์คํ์ผ #1 ๊ฐ์ฒด์งํฅ, ์๋น์ค ์์ฑํ๊ธฐ (0) | 2021.10.04 |
๊ฐ๋น์ง ์ปฌ๋ ํฐ์ TLAB (0) | 2021.09.22 |
JMX ํด, ์๋ฐ ์ดํ๋ฆฌ์ผ์ด์ ๋ชจ๋ํฐ๋ง ๋๊ตฌ (0) | 2021.09.22 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev