μΌλ§ μ λ©ν°μ€λ λ νκ²½μμ λ°μν κ°μμ± λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ volatile ν€μλλ₯Ό μ¬μ©ν μ μ΄ μλ€. κ·Έ κ³Όμ μμ μ΄ ν€μλκ° μ νν μ΄λ»κ² λμνλμ§, κ·Έλ¦¬κ³ μΈμ μ¬μ©ν΄μΌ νλμ§ κΆκΈν΄μ‘λ€. μ΄λ² κΈμμλ volatileμ λμ μ리μ νΉμ§μ μ 리ν΄λ³΄κ² λ€.

μΌλ¨ λ©λͺ¨λ¦¬ ꡬ쑰λ₯Ό μ΄ν΄λ³΄μ
CPUμ κ° μ½μ΄μλ μ±λ₯ ν₯μμ μν΄ L1 μΊμκ° λ΄μ₯λμ΄ μλ€.
CPUλ λ©λͺ¨λ¦¬μμ μ½μ΄μ¨ κ°μ μΊμμ μ μ₯νκ³ , μ΄ν λμΌν λ°μ΄ν°λ₯Ό λ€μ μ¬μ©ν λ μΊμμμ μ§μ μ½μ΄ λ λΉ λ₯΄κ² μ²λ¦¬νλ€.
λ°μ΄ν°λ₯Ό μ½μ λλ λ¨Όμ μΊμμ ν΄λΉ κ°μ΄ μλμ§ νμΈνκ³ , μμ κ²½μ° λ©μΈ λ©λͺ¨λ¦¬μμ λΆλ¬μ¨λ€.
μ΄λ° ꡬ쑰 λλ¬Έμ μ¬λ¬ μ½μ΄κ° λμμ κ°μ λ©λͺ¨λ¦¬ μ£Όμλ₯Ό μ κ·Όν λ, λ©λͺ¨λ¦¬μ κ°μ΄ λ³κ²½λμμ§λ§ μΊμκ° μμ§ κ°±μ λμ§ μμ μλ‘ λ€λ₯Έ κ°μ μ°Έμ‘°νλ νμμ΄ λ°μν μ μλ€.
νλ² μ½λλ‘ ν μ€νΈλ₯Ό ν΄λ³΄μ!!
public class VisibilityExample {
boolean active = true;
public void runTest() {
new Thread(() -> {
int counter = 0;
while (active) {
counter++;
}
System.out.println("μμ
μ€λ λ μ’
λ£. μ΅μ’
μΉ΄μ΄νΈ: " + counter);
}).start();
new Thread(() -> {
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
System.out.println("μ μ΄ μ€λ λ: μμ
μ€λ λλ₯Ό μ€μ§ν©λλ€.");
active = false;
}).start();
}
public static void main(String[] args) {
new VisibilityExample().runTest();
}
}

첫 λ²μ§Έ μ€λ λλ running νλκ·Έλ₯Ό νμΈνλ©΄μ count κ°μ κ³μ μ¦κ°μν¨λ€.
λ λ²μ§Έ μ€λ λλ 1μ΄ ν running νλκ·Έλ₯Ό falseλ‘ λ³κ²½νλ€.
μ°λ¦¬λ λ λ²μ§Έ μ€λ λκ° μ€νλλ©΄ 첫 λ²μ§Έ μ€λ λμ 무ν 루νκ° μ’ λ£λκ³ "μμ μ€λ λ μ’ λ£. μ΅μ’ μΉ΄μ΄νΈ: " + counter κ° μΆλ ₯λ κ²μΌλ‘ μμνλ€.
κ·Έλ¬λ μ€μ λ‘ μ€νν΄λ³΄λ©΄ 첫 λ²μ§Έ μ€λ λλ μ’ λ£λμ§ μλλ€.
π€ μ΄μ κ° λκΉ?
μ€λ λ 1μ running λ³μλ₯Ό μ½μ λ μμ μ CPU μΊμμ μ μ₯λ κ°μ μ°Έμ‘°νλ€.
λ°λ©΄, μ€λ λ 2λ μμ μ CPU μΊμμ μλ running κ°μ falseλ‘ λ³κ²½νκΈ° λλ¬Έμ, λ μ€λ λλ λμΌν λ³μ μ΄λ¦μ μ¬μ©νλλΌλ μλ‘ λ€λ₯Έ λ©λͺ¨λ¦¬ μμμ κ°μ λ³΄κ³ μλ μ μ΄ λλ€.
μ΄λ¬ν μ μ ν΄κ²°νκΈ° μν΄ volatileλ₯Ό μ¬μ©νλ κ²μ΄λ€.
volatile λ ν΄λΉ λ³μλ₯Ό CPU μΊμκ° μλ λ©μΈ λ©λͺ¨λ¦¬(Main Memory) λ₯Ό ν΅ν΄ μ½κ³ μ°λλ‘ λ³΄μ₯νλ ν€μλμ΄λ€.
μμ μ½λμ activeμ volatileλ₯Ό λΆμ¬λ³΄μ
package com.nexon;
public class VisibilityExample {
volatile boolean active = true;
public void runTest() {
new Thread(() -> {
int counter = 0;
while (active) {
counter++;
}
System.out.println("μμ
μ€λ λ μ’
λ£. μ΅μ’
μΉ΄μ΄νΈ: " + counter);
}).start();
new Thread(() -> {
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
System.out.println("μ μ΄ μ€λ λ: μμ
μ€λ λλ₯Ό μ€μ§ν©λλ€.");
active = false;
}).start();
}
public static void main(String[] args) {
new VisibilityExample().runTest();
}
}

μ½λλ₯Ό μ€νμν€λ©΄ 1μ΄νμ νλ‘κ·Έλ¨μ΄ μ’ λ£λλ κ²μ νμΈ ν μ μλ€.
μ΄μ²λΌ volatile ν€μλλ λ¨μν λ³μμ κ°μ λ©μΈ λ©λͺ¨λ¦¬μμ μ½κ³ μ°λλ‘ λ³΄μ₯ν΄ κ°μμ± λ¬Έμ λ₯Ό ν΄κ²°νλ€.
νμ§λ§ μμμ±(atomicity) μ 보μ₯νμ§ μκΈ° λλ¬Έμ, 볡ν©μ μΈ μ°μ°(μ: count++)μμλ μ¬μ ν λκΈ°ν(synchronized)κ° νμνλ€.
μ¦, volatileμ βμ€λ λ κ° κ°μ΄ μ¦μ λ°μλμ΄μΌ νλ κ²½μ°βμλ§ μ¬μ©ν΄μΌ νλ©°, λμμ μ¬λ¬ μ€λ λκ° κ°μ μμ νλ μν©μ΄λΌλ©΄ λ½(lock) μ μ¬μ©ν΄μΌ νλ€.
volatile ν€μλλ λμμ± νλ‘κ·Έλλ°μμ λ°μν μ μλ κ°μμ± λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ μ¬μ©λλ€. κ°μμ± λ¬Έμ λ, μ¬λ¬ μ€λ λκ° λμμ λ³μλ₯Ό μ¬μ©ν λ, κ° μ€λ λμ CPU μΊμμ λ©μΈ λ©λͺ¨λ¦¬(RAM) κ° κ°μ΄ μΌμΉνμ§ μμ ν μ€λ λκ° λ³κ²½ν κ°μ λ€λ₯Έ μ€λ λκ° λ°λ‘ νμΈνμ§ λͺ»νλ μν©μ μλ―Ένλ€. volatileμ λΆμΈ λ³μλ λͺ¨λ μ€λ λκ° λ©μΈ λ©λͺ¨λ¦¬μμ μ§μ μ½κ³ μ°λλ‘ λ³΄μ₯λλ―λ‘, κ°μ λ³κ²½μ΄ μ¦μ λ€λ₯Έ μ€λ λμ λ°μλλ€.
μ΄ ν€μλλ μ€λ λ κ° μνλ₯Ό λ¨μν 곡μ νλ νλκ·Έ λ³μλ, μ½κΈ°/μ°κΈ° μ°μ°λ§ νμν κ²½μ°μ μ¬μ©λλ€. νμ§λ§ volatileμ μμμ±(atomicity)μ 보μ₯νμ§ μκΈ° λλ¬Έμ, μ¬λ¬ μ€λ λκ° λμμ κ°μ μμ νλ λ³΅ν© μ°μ°μμλ synchronizedλ Atomic ν΄λμ€λ₯Ό μ¬μ©ν΄μΌ νλ€.
μ°Έκ³