2016-10-04 2 views
1

나는 두 개의 스레드 T1 시작 1,3,5, ..... 및 스레드 두 개의 T2 인쇄 2,4,6 .... 아래 코드를 시작합니다.스레드 실행을 예측할 수 없습니다

public class T1T2Print { 
    public static void main(String[] args) { 
     Counter c = new Counter(); 
     c.count = 1; 
     printThread t1 = new printThread(c); 
     Thread T1 = new Thread(t1); 
     T1.setName("T1"); 
     printThread t2 = new printThread(c); 
     Thread T2 = new Thread(t2); 
     T2.setName("T2"); 
     T2.start(); 
     T1.start(); 
    } 

} 

class printThread implements Runnable { 
    public Counter count; 
    public int reminder; 



public printThread(Counter count) { 
    this.count = count; 
} 

public void run() { 
    for (int i = 1; i <= 5; i++) { 
     synchronized (count) { 
      String name = Thread.currentThread().getName(); 

      if (count.count % 2 != 0 && !name.equals("T1")) { 
       try { 
        count.wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } else { 
       System.out.println(name + " :: " + count.count); 
       count.count++; 
       count.notify(); 
      } 

      if (count.count % 2 == 0 && !name.equals("T2")) { 
       try { 
        count.wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } else { 
       System.out.println(name + " :: " + count.count); 
       count.count++; 
       count.notify(); 
      } 

     } 
    } 
} 
} 

출력은 다음과 같습니다 :

T1 :: 1 
T2 :: 2 
T1 :: 3 
T2 :: 4 
T1 :: 5 
T2 :: 6 
T1 :: 7 
T2 :: 8 
T1 :: 9 
T2 :: 10 

하지만 난

T1.start(); 
T2.start(); 

다음과 같이 출력 변경, 왜이 문제

에 스레드를 시작하는 순서를 변경하는 경우
T1 :: 1 
T2 :: 2 
T2 :: 3 
T2 :: 4 
T2 :: 5 
T2 :: 6 
T2 :: 7 
T2 :: 8 
T2 :: 9 
T2 :: 10 
T2 :: 11 
T1 :: 12 
T1 :: 13 
T1 :: 14 
T1 :: 15 
T1 :: 16 
T1 :: 17 
T1 :: 18 
T1 :: 19 
+0

내 생각 엔 당신이 여기 세부에서 분명하지 않다 뭔가를 잘못하고있는 것입니다. 'wait()'를 호출하면 그렇게해야합니다. 기다리고 있음을 보여주기 위해 print 문을 추가합니다. –

답변

1

if에는 몇 가지 문제가 있습니다. 각 반복마다 카운터가 두 번 증가 할 수 있습니다.

예를 들어 카운터가 2 일 때 T2 스레드를 만들려면 값을 두 번 증가시킵니다. count.count % 2 != 0은 false이므로 else가 실행되고 카운터가 증가합니다. 카운터가 이제 3이고 count.count % 2 == 0이 거짓이므로 두 번째 else도 실행되고 카운터가 증가하고 예기치 않은 결과가 발생하므로 두 번째 if도 false입니다.

귀하의 if 문은 다음과 같이 뭔가에 고정 될 수있다 :

public void run() { 
    for (int i = 1; i <= 5; i++) { 
     synchronized (count) { 
      String name = Thread.currentThread().getName(); 

      if (name.equals("T1")) { 
       while (count.count % 2 == 0) { 
        try { 
         count.wait(); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 
       System.out.println(name + " :: " + count.count); 
       count.count++; 
       count.notify(); 
      } else if (name.equals("T2")) { 
       while (count.count % 2 != 0) { 
        try { 
         count.wait(); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 
       System.out.println(name + " :: " + count.count); 
       count.count++; 
       count.notify(); 
      } 
     } 
    } 
} 
+0

잠시 동안은 스핀 록과 같습니다. – user2478236

+0

'대기'후 다시 상태를 확인하는 것이 좋습니다. 그것은'while'을'if'로 대체하여 작동합니다. –

2

추가하자. System.out.println(name + " :: waits"); 전에 count.wait() 전화하십시오.

그런 다음 첫 번째 경우 로그 :

T2 :: waits 
T1 :: 1 
T1 :: waits 
T2 :: 2 
T2 :: waits 
T1 :: 3 
T1 :: waits 
T2 :: 4 
T2 :: waits 
T1 :: 5 
T1 :: waits 
T2 :: 6 
T2 :: waits 
T1 :: 7 
T1 :: waits 
T2 :: 8 
T2 :: waits 
T1 :: 9 
T1 :: waits 
T2 :: 10 

2 차의 경우 로그 : 당신이 두 번째 경우에서 볼 수 있듯이 스레드가 잠을하지 않는

T1 :: 1 
T1 :: waits 
T2 :: 2 
T2 :: 3 
T1 :: 4 
T1 :: 5 
T1 :: 6 
T1 :: 7 
T1 :: 8 
T1 :: 9 
T1 :: 10 
T1 :: 11 
T2 :: 12 
T2 :: 13 
T2 :: 14 
T2 :: 15 
T2 :: 16 
T2 :: 17 
T2 :: 18 

. 왜? 두 번째 경우에는 각 스레드가 카운터 을 두 번 (한 번에 if, 한 번에 두 번째로 if) 두 번 증가 (동기화 된 방식으로 수행하기 때문에)합니다. (나는이 논리를 원하지 않는다고 추측 할 수 있으며 이것은 여러분이 만든 오류입니다). 사례의 차이점은 무엇입니까? 첫 번째 경우는 T2이 먼저 시작되고 첫 번째와 두 번째에 알림을 기다린 후 깨어나서 깨어나서 두 번째 if (예 : 카운터를 한 번만 증가 (및 인쇄))합니다. 그래서 이유가 있습니다.

관련 문제