while(1) work();
article thumbnail
반응형

문제

class Q2 {
    static long value;

    public static void main(String[] args) {
        Runnable r = () -> {
            for (int i = 0; i < 100000; i++) value++;
        };

        Thread t1 = new Thread(r);
        Thread t2 = new Thread(r);
        
        t1.start();
        t2.start();

        t1.join();
        t2.join(); //작업 종료 대기
        
        System.out.println("value = " + value);
    }
}

출력된 값은 200000인가?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

정답

아니다.

200000에 한참 못미치는 값이 출력된다.

 

꼬리 문제

그럼, 문제 1( https://engine-it.tistory.com/179 ) 처럼 value에 volatile 키워드를 붙이면 해결할 수 있는가?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

꼬리 정답

아니다.

 

volatile 키워드만으로는 해결할 수 없다.

이 문제는 가시성과 동시성 모두 고려하여 해결하여야 한다.

 

volatile 키워드를 붙임으로써 아까에 비해 출력값이 200000에 아주 조금은 더 근접해졌다.

이는 가시성이 해결되었기 때문일 수 있다. (확실치 않음. 변인이 너무 많음.)

 

value++ 는

value를 읽기, 값 1 더하기, value에 저장하기

세 동작이 이루어져야 하기 때문에 원자적이지 않다.

 

두 스레드가 value를 읽은 상태에서

각각 1씩 더하고

value에 저장하면...

 

2가 더해지는 것이 아니라 1만 더해진다. (초기에 같은 값을 읽었으므로)

 

따라서, 아래와 같이 코드를 수정해야 한다.

volatile 키워드는 불필요하다. synchronized 키워드가 이를 보장해준다. (https://docs.oracle.com/javase/specs/jls/se19/html/jls-17.html#jls-17.4.4)

 

class Q2 {
    static long value;

    public static void main(String[] args) throws InterruptedException{
        Runnable r = () -> {
            for (int i = 0; i < 100000; i++) {
                synchronized (Q2.class) {
                    value++;    
                }
            }
        };

        Thread t1 = new Thread(r);
        Thread t2 = new Thread(r);
        
        t1.join();
        t2.join(); //작업 종료 대기

        Thread.sleep(10000); //충분한 시간 대기
        
        System.out.println("value = " + value);
    }
}

 

반응형
profile

while(1) work();

@유호건

❤️댓글은 언제나 힘이 됩니다❤️ 궁금한 점이나 잘못된 내용이 있다면 댓글로 남겨주세요.

검색 태그