Java Adv 06 - Synchronized Ex

Thread Synchronized

public class SyncTest1BadMain {

    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        Runnable task = new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 10000; i++) {
                    counter.increment();
                }
            }
        };
        Thread thread1 = new Thread( task );
        Thread thread2 = new Thread( task );

        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println( "결과: " + counter.getCount() );
    }

    static class Counter {

        private int count = 0;

        public void increment() {
            count = count + 1;
        }

        private int getCount() {
            return count;
        }
    }
}

image

기대한 값은 20000인데 왜 저런 값이 나올까?

image image image

스레드 2개가 increment() 를 호출하기 때문에 기대하는 count 의 결과는 2가 되어야 한다. 하지만 둘이 동시에 실행되기 때문에, 처음에 둘다 count 의 값을 0으로 읽었다. 여기서 잘 보면 count 의 값을 읽어서 계산하는 부분과 그 결과를 count 에 다시 넣는 부분으로 나누어져 있다. 따라서 여러 스레드가 동시에 실행되면 지금과 같은 문제가 발생할 수 있다. 따라서 synchronized 키워드를 사용해서 한 번에 하나의 스레드만 실행할 수 있도록, 안전한 임계 영역을 만들어야 한다. (syncronized는 임계영역) synchronized를 붙임으로써 임계영역을 한 번에 걸어잠글 수 있는 락(lock)을 제공한다. 이제 여러 스레드 중 하나의 스레드가 먼저 임계영역 안으로 들어오면 락이 걸리고, 나머지 스레드들은 먼저 들어간 스레드가 작업을 마치고 임계영역 밖으로 나오기 전까지 대기하게 된다. 참고로 지역변수 localValue는 다른 스레드와 절대 공유하지 않는다. thread1, thread2의 각각의 메모리 영역에서 생성되는 값이다.

Reference

김영한님의 자바 강의

https://stackoverflow.com/questions/20906548/why-is-synchronized-block-better-than-synchronized-method



© 2022. by taewoo

Powered by taewoo