멀티 쓰레드는 CPU를 최대한 활용할 수 있는 도움을 주었다
하지만 쓰레드는 이와 동시에 위험을 주었다
위험이란 원자적이지 못한 메소드를 여러개의 쓰레드가 동시에 접근하여 수행할때
그 결과값이 우리가 기대하는 값과는 다를 수 있다는 것이다.
아래 예시를 보자
----------------------------------------------------------------------------------------
*Count Class : 카운트 클래스는 num이라는 변수와 count()라는 num을 1씩 증가시키는 메소드를 가지고 있다
----------------------------------------------------------------------------------------1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Count{ public int num; public void count() { try { Thread.sleep(1000); num++; } catch (InterruptedException e) { e.printStackTrace(); } } } | cs |
----------------------------------------------------------------------------------------
*Task Class : Task 클래스는 Counter객체를 멤버변수로 가지고 있으며
스레드에서 counter객체의 num변수의 값이 5보다 작을때 까지만
count()메소드를 실행시킨다.
또한 Runnable을 구현하여 스레드 객체가 생성자에서 받을 수 있도록 한다.
----------------------------------------------------------------------------------------
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Task implements Runnable{ Counter counter = new Counter(); @Override public void run() { // TODO Auto-generated method stub while(counter.num < 5) counter.count(); System.out.println("수 : " + counter.num); } } | cs |
----------------------------------------------------------------------------------------
*Test Class : Test클래스는 두개의 스레드를 생성하며 Task를 인자로 넘겨 주어 수행한다
----------------------------------------------------------------------------------------1 2 3 4 5 6 7 8 9 10 11 | public class Test { public static void main(String[] args) { Task task = new Task(); Thread t1 = new Thread(task); Thread t2 = new Thread(task); t1.start(); t2.start(); } } | cs |
----------------------------------------------------------------------------------------
*결과 : Task 클래스에서 While문의 조건이 5보다 작을때까지만 수행하라고 했으나
결과값은 6이 나왔다.
----------------------------------------------------------------------------------------result : 수 : 5 // Thread1
수 : 6 // Thread2
*** 이유 : count() 메소드의 num++ 값은 한줄의 코드로 원자적인것 처럼 보이나
스레드가 1. 값에 접근하고
2. 그값을 증가시키고
3. 다시 그값을 적용하는
세 단계를 거친다 따라서 값을 증가시키고 그 값을 적용하기전 다른 스레드가
그변수에 접근한다면 증가된값이 적용되기 이전의 값을 취하기 때문에
결과값이 다르게 나올 수 있다.
ex)
Thread1 -> num ( 4 ) // 아직 num이 4이기 때문에 ++
Thread2 -> num ( 4 ) // Thread2 가 접근했을 때에도 값이 4이기 때문에 ++
Thread1 -> num ( 5 ) // Thread1이 count()를 실행하고 난 뒤 num은 5
Thread2 -> num ( 6 ) // Thread2가 count()를 실행하고 난 뒤 num은 6
@@@ 해결법
다음 포스팅에서 다루겠다
'Language > Java' 카테고리의 다른 글
Java - 자바 가상머신(JVM: Java Virtual Machine) (0) | 2018.10.28 |
---|---|
Java - 쓰레드 동기화 (Synchronized) (0) | 2018.08.26 |
Java - InputStream 의 read()메소드는 왜 int형을 반환 하는가 (0) | 2018.08.25 |
Java - String 과 StringBuffer 클래스 (0) | 2018.08.25 |
Java - equals 과 == 차이 (0) | 2018.08.25 |