본문 바로가기

Java Programming

Multi-Threading ④ Concurrency Problem

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
앞서 말한 자바에서의 스레드의 특징중에, 잠재적인 문제 발생의 위험이 있다고 했었는데요, 첫째로 병행성의 문제에 대해서 알아보도록 하겠습니다 ^^ 병행성의 문제라는 것을 풀어서 이야기 하자면, 여러개의 스레드 객체가 한개의 리소스를 공유하기 때문에 발생하는 문제점이라는 겁니다! 일단 말로 이야기 하면 지루하기 때문에 소스코드를 보시면서 이야기 하겠습니다!

public class ConcorrencyTrouble implements Runnable {

      private int total;

      public void run() {

            for (long i = 0; i < 10; i++) {

                   increase();

                   System.out.println("total value is :" + total);

            }

      }

      public void increase() {

            int index = total;

            System.out

                          .println(Thread.currentThread().getName() + " 스레드가 일을 시작합니다!");

            total = index + 1;

      }

      public static void main(String[] args) {

            ConcorrencyTrouble work = new ConcorrencyTrouble();

            Thread th1 = new Thread(work);

            Thread th2 = new Thread(work);

            Thread th3 = new Thread(work);

            Thread th4 = new Thread(work);

            th1.setName("한산");

            th2.setName("동규");

            th3.setName("석겸");

            th4.setName("기선");

            th1.start();

            th2.start();

            th3.start();

            th4.start();

      }

}

간략하게 이야기 하자면 ^^; total 이라는 멤버 변수를 4개의 스레드가 10씩 올리는 작업을 수행하여 40이라는 값을 출력하도록 하는겁니다. 하지만 40이라는 값이 나오게 될런지 한번 소스코드를 실행 해보도록 합시다.

사용자 삽입 이미지

-_-;; 40이라는 값은 커녕.. 실행 시킬때 마다 값이 틀린 그런 현상이 일어납니다. 이것이 바로 병행성의 문제입니다. 어디서 이런 문제점이 발생하는가?? 바로 increase() 라는 메소드 내부에서 일어납니다. 메소드 내에 문법상의 문제나 런타임 오류가 있는것이 아니라, 일단 스레드 4개가 순차적으로 실행이 될것이라는 생각과 더불어, '병행' 이라는 점에 초점을 맞추지 않았기 때문입니다. 다음과 같은 스레드 객체의 특징을 알아 두시는 것이 좋습니다.

스레드 스케줄러가 스레드의 실행 순서를 결정합니다.

병행은 동시에 수행된다는 것을 의미합니다.

객체 생성 순서에 관계 없이 스레드는 스레드 스케줄러에 의해서 실행 됩니다.
엥?? 스레드 스케줄러가 뭐냐구요?? 스레드 스케줄러라는 것은 말그대로 스레드의 실행순서를 정하는 역할을 담당합니다. 스레드 스케줄러의 특징은 아래와 같습니다.

스레드의 실행순서를 정한다.

API에는 스케줄러에 대한 호출 메소드가 전혀 없다.

JVM에 따라서 다르게 구현되어 있다. 따라서 스케줄러가 어떤 특별한 방식으로 작동할 것을 가정하고 프로그램을 만들면 안 된다.
세번째 특징을 보시면, 왜 위와 같은 병행성의 문제가 발생했는지를 알 수 있습니다. 순차적으로 실행이 되어서 40이라는 값을 기대하고 멀티스레드를 이용한 프로그램을 작성했기 때문에, 오류를 범하게 되었습니다. 근데 왜 이상한 값이 출력이 되었을까요?? 어쨌든 40으로 가지 않을까요??

'병행성' 이라는 것에 염두를 두셔야 합니다. 동시에 실행이 되기 때문에 어떤 스레드가 먼저 실행 될지는 프로그래머가 조작할 수 없습니다. 따라서 한 스레드가 값을 열람하기 일보직전에 다른 스레드가 값을 증가 시키거나, 증가 시킨후에 다시 원래 변수에 저장하기전에 다른 스레드가 원래 변수를 또 증가시키는 경우도 발생할 수 있다는 것입니다.