동기화


스레드의 문제점

스레드들이 여러 개 동시의 작업을 진행하기 때문에 공유자원의 문제가 발생한다.


동기화(Synchronization)의 정의

줄서기(번갈아 가면서 순서대로 공유자원 사용하기)


동기화의 기법

synchronized 블록(자원을 사용할 때 자원에 락(Lock)을 거는 방식)

wait() 와 notify()


동기화가 보장되지 않는 예제

public class NotSyncDataMain {
    public static Data data = new Data();

    public static void main(String[] args) {
        System.out.println("main 시작");
        Tom t = new Tom();
        Jane j = new Jane();
        t.start();
        j.start();
        System.out.println("main 종료");
    }
}

class Data {
    public int i = 0;
}

class Tom extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100000000; i++) {
            NotSyncDataMain.data.i++;
        }
        System.out.println("Tom :" + NotSyncDataMain.data.i);
    }
}

class Jane extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100000000; i++) {
            NotSyncDataMain.data.i++;
        }
        System.out.println("Jane :" + NotSyncDataMain.data.i);
    }
}
결과
main 시작
main 종료
Tom :102920518
Jane :111359606


동시에 실행되는 것이 스레드 이기 때문에 Tom과 Jane은 공유자원 Data data의 멤버변수 i의 값을 100000번씩 200000번 증가시킬 것이다. 결과는 200000이 나와야 하지만 전혀 다른 결과가 나온 것을 알 수 있다. 이것은 i에 접근할 때 순서대로 중복되지 않게 번갈아 가면서 작업을 한 것이 아니라 어느 시점에 Tom과 Jane이 동시에 값을 읽고 증가 시켰기 때문에 발생하는 문제 이다.


동기화 보장 예제

public class SyncDataMain {
    public static Data data = new Data();

    public static void main(String[] args) {
        System.out.println("main 시작");
        Tom t = new Tom();
        Jane j = new Jane();
        t.start();
        j.start();
        System.out.println("main 종료");
    }

}

class Data {
    public int i = 0;
}

class Tom extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            synchronized (SyncDataMain.data) {
                SyncDataMain.data.i++;
            }
        }
        System.out.println("Tom :" + SyncDataMain.data.i);
    }
}

class Jane extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            synchronized (SyncDataMain.data) {
                SyncDataMain.data.i++;
            }
        }
        System.out.println("Jane :" + SyncDataMain.data.i);
    }
}

결과

main 시작

main 종료

Tom :1000

Jane :2000


동기화 보장을 위한 synchronized 블록 즉 임계 영역을 설정했기 때문에 Tom과 Jane은 동시에 수를 증가시키지는 않느다. 어트 한 시점에 하나의 스레드만이 공유자원의 값을 증가시키기 때문에 최종 결과는 2000 이 나오는 것이다.


* 다만 동기화를 사용할 경우 임계 영역이 있기 때문에 대기 시간이 많이 발생되고 그로 인해 성능에 악영향을 줄수 있다.



'JAVA > in 기초' 카테고리의 다른 글

[JAVA8]자바의 다중 상속 관련 내용  (0) 2014.12.19
[JAVA8]Stream 맛보기  (0) 2014.12.02
스레드 기본(3)  (0) 2014.03.05
스레드 기본(2)  (0) 2014.03.05
static 변수는 하나의 프로세스에서 하나의 값만 가진다.  (0) 2014.03.05
스레드 기본(1)  (0) 2014.03.05
Posted by lahuman

댓글을 달아 주세요