Item 78. Mutable Data Sharing

곡유 쀑인 κ°€λ³€ λ°μ΄ν„°λŠ” 동기화해 μ‚¬μš©ν•˜λΌ

synchronized ν‚€μ›Œλ“œλŠ” ν•΄λ‹Ή λ©”μ„œλ“œλ‚˜ 블둝을 ν•œ λ²ˆμ— ν•œ μŠ€λ ˆλ“œμ”© μˆ˜ν–‰ν•˜λ„λ‘ 보μž₯ν•˜λ©°, μ•„λž˜μ˜ νŠΉμ§•μ„ κ°€μ§„λ‹€.

  • ν•œ 객체가 μΌκ΄€λœ μƒνƒœλ₯Ό κ°€μ§€κ³  μƒμ„±λ˜μ—ˆμ„ λ•Œ, ν•΄λ‹Ή 객체에 μ ‘κ·Όν•˜λŠ” λ©”μ„œλ“œλŠ” ν•΄λ‹Ή 객체이 Lock을 νšλ“

  • Lock을 νšλ“ν•œ λ©”μ„œλ“œλŠ” 객체의 μƒνƒœλ₯Ό ν™•μΈν•˜κ±°λ‚˜ λ³€κ²½ν•  수 있음

  • λ©”μ„œλ“œ 싀행이 μ’…λ£Œλ˜λ©΄ Lock을 ν•΄μ œ

  • 동기화 μ—†μ΄λŠ” ν•œ μŠ€λ ˆλ“œκ°€ 객체의 일관성이 κΉ¨μ§„ μƒνƒœλ₯Ό 보게 될 수 있음

    • λ™κΈ°ν™”λŠ” λ©”μ„œλ“œλ‚˜ 블둝에 λ“€μ–΄κ°„ μŠ€λ ˆλ“œκ°€ 객체의 일관성이 κΉ¨μ§„ μƒνƒœλ₯Ό 보지 λͺ»ν•˜λ„둝 보μž₯

Javaμ—μ„œ κ°€λ³€ 데이터 μŠ€λ ˆλ“œκ°„ 톡신

μ•„λž˜ μ½”λ“œλŠ” boolean ν•„λ“œλ₯Ό κ²€μ‚¬ν•˜λ©΄μ„œ κ·Έ 값이 trueκ°€ μ•„λ‹ˆλ©΄ λ¬΄ν•œ 루프λ₯Ό 돌며 값을 μ¦κ°€μ‹œν‚€λŠ” μ½”λ“œμ΄λ‹€.

class StopThread {

    private static boolean stopRequested;

    public static void main(String[] args) throws InterruptedException {

        Thread backgroundThread = new Thread(() -> {
            int i = 0;
            while (!stopRequested) {
                i++;
                System.out.println(i);
            }
        });

        backgroundThread.start();

        TimeUnit.SECONDS.sleep(1);
        stopRequested = true;
    }
}

1초 ν›„ 메인 μŠ€λ ˆλ“œμ—μ„œ stopRequested ν•„λ“œμ˜ 값을 true둜 λ³€κ²½ν•˜κ³  μžˆμ§€λ§Œ, μ‹€μ œλ‘  λ³€κ²½λœ 값을 λ°”λ‘œ 읽지 λͺ»ν•˜λŠ” κ²½μš°κ°€ λ°œμƒν•  수 μžˆλ‹€. ** μ‹€ν–‰ ν™˜κ²½μ— 따라 1초 후에 λ°”λ‘œ μ’…λ£Œλ  μˆ˜λ„ μžˆλ‹€.

synchronized λ©”μ„œλ“œλ₯Ό μ΄μš©ν•œ 동기화

ν•΄λ‹Ή 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„  stopRequested ν•„λ“œμ— μ ‘κ·Όν•˜λŠ” λ©”μ„œλ“œλ₯Ό 동기화 ν•˜λŠ” 방법이 μžˆλ‹€.

μ“°κΈ°(requestStop)와 읽기(stopRequested) λ©”μ„œλ“œ λͺ¨λ‘ synchronized ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜κ³  μžˆλŠ”λ°, 읽기와 μ“°κΈ° μ „λΆ€ synchronized ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠμœΌλ©΄ 동기화가 μ œλŒ€λ‘œ 이루어지지 μ•ŠλŠ”λ‹€.(κ°„ν˜Ή 잘 λ™μž‘ν•˜λŠ” 것 처럼 보일 수 μžˆμ§€λ§Œ μ‹€μ œλ‘  κ·Έλ ‡μ§€ μ•Šλ‹€.)

volatile ν•„λ“œλ₯Ό μ΄μš©ν•œ 동기화

volatile ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ ν•΄λ‹Ή ν•„λ“œλ₯Ό 읽고 μ“°λŠ” λ™μž‘μ΄ 항상 메인 λ©”λͺ¨λ¦¬μ— λ°˜μ˜λ˜λ„λ‘ 보μž₯ν•˜λŠ” 방법이 μžˆλ‹€.

volatile μ£Όμ˜μ‚¬ν•­

μœ„μ˜ λ¬Έμ œλŠ” volatile ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 문제λ₯Ό ν•΄κ²°ν–ˆμ§€λ§Œ, ν•΄λ‹Ή ν‚€μ›Œλ“œλŠ” ν•„λ“œλ₯Ό 읽고 μ“°λŠ” ν†΅μ‹ λ§Œ 보μž₯ν•˜λ©°, λ™μ‹œμ„±μ„ 보μž₯ν•˜μ§€λŠ” μ•ŠλŠ”λ‹€.

μœ„ μ½”λ“œλ₯Ό 싀행해보면 2000000이 λ‚˜μ™€μ•Ό ν•  것 κ°™μ§€λ§Œ, μ‹€μ œλ‘œλŠ” 1592872(2000000이 μ•„λ‹Œ κ°’)κ°€ λ‚˜μ˜€λŠ” 것을 확인할 수 μžˆλ‹€. μ΄λŠ” volatile ν‚€μ›Œλ“œλŠ” ν•΄λ‹Ή ν•„λ“œλ₯Ό 읽고 μ“°λŠ” ν†΅μ‹ λ§Œ 보μž₯ν•˜λ©°, λ™μ‹œμ„±μ„ 보μž₯ν•˜μ§€λŠ” μ•ŠκΈ° λ•Œλ¬Έμ΄λ‹€.

synchronized 블둝을 μ΄μš©ν•œ 동기화

처음 λ‚˜μ™”λ˜ synchronized ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ ν•΄λ‹Ή ν•„λ“œλ₯Ό 읽고 μ“°λŠ” 톡신과 λ™μ‹œμ„±μ„ 보μž₯ν•˜λŠ” 방법이 μžˆλ‹€.

Atomic 클래슀λ₯Ό μ΄μš©ν•œ 동기화

λ©€ν‹° μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œ 동기화 문제λ₯Ό λ³„λ„μ˜ synchronized ν‚€μ›Œλ“œ 없이 ν•΄κ²°ν•  수 μžˆλŠ” λ°©λ²•μœΌλ‘œ java.util.concurrent.atomic νŒ¨ν‚€μ§€μ— μžˆλŠ” Atomic 클래슀λ₯Ό μ‚¬μš©ν•˜λŠ” 방법이 μžˆλ‹€. (λ‚΄λΆ€μ μœΌλ‘œ volatile ν‚€μ›Œλ“œμ™€ CAS μ•Œκ³ λ¦¬μ¦˜μ„ μ‚¬μš©ν•˜μ—¬ λ™μ‹œμ„± 문제λ₯Ό ν•΄κ²°ν•˜κ³  μžˆλ‹€.)

κ²°λ‘ 

κ°€λ³€ 데이터λ₯Ό κ³΅μœ ν•˜λŠ” 방법을 λ‹€λ£¨μ—ˆμ§€λ§Œ, 더 λ³΅μž‘ν•œ λ‘œμ§μ—μ„œλŠ” λ¬Έμ œκ°€ μ–΄λ””μ„œ λ°œμƒν• μ§€ μ˜ˆμΈ‘ν•  수 μ—†μœΌλ―€λ‘œ κ°€λ³€ 데이터λ₯Ό κ³΅μœ ν•˜μ§€ μ•ŠλŠ” 방법을 μ‚¬μš©ν•˜λŠ” 것이 κ°€μž₯ μ’‹λ‹€. λ§Œμ•½ λ©€ν‹° μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œ κ°€λ³€ 데이터λ₯Ό κ³΅μœ ν•΄μ•Ό ν•œλ‹€λ©΄ μ•„λž˜ 사항을 μ£Όμ˜ν•˜μž.

  • ν•΄λ‹Ή 데이터λ₯Ό 읽고 μ“°λŠ” λ©”μ„œλ“œ μ „λΆ€ synchronized ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 동기화

  • volatile ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ 톡신은 보μž₯λ˜μ§€λ§Œ, λ™μ‹œμ„±μ€ 보μž₯λ˜μ§€ μ•ŠλŠ” 것을 주의

  • κ°€λ³€ 데이터가 java.util.concurrent.atomic νŒ¨ν‚€μ§€μ—μ„œ μ œκ³΅ν•œλ‹€λ©΄ ν•΄λ‹Ή 클래슀λ₯Ό 고렀해도 μ’‹μŒ

Last updated

Was this helpful?