2013-07-15 2 views
0

두 개의 스레드를 시작하는 코드 스 니펫을 작성했습니다. 한 스레드는 모든 홀수를 인쇄하고 다른 스레드는 모든 짝수를 인쇄합니다. 두 스레드의 적절한 인터리빙을 위해 고유 한 잠금 및 스레드 통신 명령 조합을 사용했습니다. 여기 여기 2 개의 스레드, 2 개의 동기화 된 블록 및 1 개의 고유 잠금

public class threadEvenOdd implements Runnable 
{ 
    static Boolean isOdd=true; 
    int count = 10; 
    Boolean value; 
    static int c=1; 
    static Object lock = new Object(); 

    threadEvenOdd(Boolean temp) 
    { 
     value = temp; 
    } 
    public void run() 
    { 
     if(value) 
     { 
      printOdd(count); 
     } 
     if(!value) 
     { 
      printEven(count); 
     } 
    } 
    void printOdd(int count) 
    { 
     try 
     { 
      for(int i=0;i<count/2;i++) 
      { 
       //System.out.println("odd enters lock"); 
       synchronized(lock) 
       { 
        if(!isOdd) 
        { 
         //System.out.println("odd in barrier"); 
         lock.wait(); 
        } 
        System.out.println(c); 
        c++; 
        isOdd = false; 
        //System.out.println("odd notifies"); 
        lock.notify(); 
       } 
      } 
     } 
     catch(Exception e) 
     { 
      System.out.println(e); 
     } 
    } 
    void printEven(int count) 
    { 
     try 
     { 
      for(int i=0;i<count/2;i++) 
      { 
       //System.out.println("even enters lock"); 
       synchronized(lock) 
       { 
        if(isOdd) 
        { 
         //System.out.println("even in barrier"); 
         lock.wait(); 
        } 
        System.out.println(c); 
        c++; 
        isOdd = true; 
        //System.out.println("even notifies"); 
        lock.notify(); 
       } 
      } 
     } 
     catch(Exception e) 
     { 
      System.out.println(e); 
     } 
    } 
    public static void main (String args[]) 
    { 
     threadEvenOdd th1 = new threadEvenOdd(true); 
     threadEvenOdd th2 = new threadEvenOdd(false); 
     Thread t1 = new Thread(th1); 
     t1.setName("odd"); 
     Thread t2 = new Thread(th2); 
     t2.setName("even"); 
     //System.out.println(t1.getName() + " starts"); 
     t1.start(); 
     //System.out.println(t2.getName() + " starts"); 
     t2.start(); 
    } 
} 

내 질문들 내 코드 :

짝수 스레드가 printEven() 함수에 실행되는 동안 홀수 스레드의 printOdd() 함수에서 실행
  1. . 두 스레드에 대해 하나의 고유 잠금을 사용하고 있습니다. 두 스레드가 각각의 동기화 된 블록에 동시에 존재할 수있는 방법을 이해하지 못합니다. 왜냐하면 같은 잠금을 사용하기 때문입니다.

  2. 내 코드에서 스레드 통신 문 (알림, 대기)을 제거했지만 여전히 원하는 출력을 얻었습니다. 나는 지금 내 코드가 실제로 쓰레드 통신문을 필요로하는지 궁금하다.

  3. 필자는 내 자신의 코드를 이해하는 데 어려움을 겪고 있기 때문에 멀티 스레딩 개념에 대한 이해를 계속해야한다고 생각합니다. p 내가 가지고있는 멀티 스레딩 개념만을 사용하여 더 나은 방법을 설명 할 수 있습니까? 익숙한?

답변

1
  • 각 스레드는 실행 코드를 통해 자신의 경로를 갖는다. 두 스레드가 똑같은 코드를 실행하더라도 코드를 통해 코드 실행을 통해 여전히 두 개의 별개의 실행 지점을 갖습니다. 스레드가 동기화 된 명령문에 도달하면 잠금을 사용할 수있을 때까지 대기합니다. 동일한 잠금에 의해 보호되는 동기화 된 블록 안에 다른 스레드가없는 경우에만 동기화 된 블록으로 들어갑니다.

  • 알림/대기 명령문을 제거했지만 동일한 결과가 계속 표시 될 수 있습니다. 비교적 큰 값인 count 필드를 사용하여 이것을 시도 했습니까?

  • 이 프로그램에서 어떤 출력물을 출력해야하는지 지정하지 않았으므로 지금은이 질문에 대답하기가 어렵습니다. "1,3,5,7,9,2,4,6,8"은 유효한 출력입니까? "1,3,2,4,6,5,7,9,8"입니까? 아니면 "1,2,3,4,5,6,7,8,9"가 유일한 유효한 출력입니까?

  • 사용의 notifyAll() 대신

  • 스레드간에 공유되는 상태를 최소화 통지 : 그것은 여기에 몇 가지 간단한 포인트 말했다. 이 경우 isOddc을 공유합니다. 전자는 c % 2 == 1을 통해 후자로부터 계산할 수 있습니다. 따라서 스레드를 공유 데이터로 유지하는 대신 홀수 컴퓨팅을 수행 할 수 있습니다.

  • 정적 필드를 통해 공유하는 대신 개체 (인스턴스 필드 사용)를 만들고이 개체를 각 스레드의 생성자에 전달합니다. 그런 다음 객체 자체를 잠금으로 사용할 수 있습니다.여기

는 같이하는 방법은 다음과 같습니다

그것에 대해 좋은 점은 당신이 다음과 같은 sharedData에 실제 방법 (정의를 시작 할 수 있다는 것입니다
class SharedData { 
    int c; 
    boolean isOdd; 
} 

class ThreadEvenOdd { 
    SharedData sharedData; 

    pubic ThreadEvenOdd(SharedData sd) { this.sharedData = sd } 

    ... 

    void printOdd(int count) { 
    try { 
     for(int i=0;i<count/2;i++) { 
     synchronized(sharedData) { 
      if(!sharedData.isOdd) { ... } 
      System.out.println(sharedData.c); 
      sharedData.c++; 
      sharedData.isOdd = false; 
      lock.notify(); 
      } 
     } 
     } 
    } 
    catch(Exception e) { 
     System.out.println(e); 
    } 
    } 

: c을 높이고에 isOdd을 설정하는 방법을 c의 값을 기반으로 적절한 값을 지정하면 스레드 클래스의 코드가 훨씬 단순 해지고 데이터 처리와 동기화/알림이 인터리브되지 않게되어 코드가 읽기 쉽고 오류가 발생하기 어렵게됩니다.

+0

이탈리아 Maman 답장을 보내 주셔서 감사합니다. 내 출력은 {1,2,3,4,5,6,7,8, ....}로되어 있습니다. 제 수를 늘리고 스레드 상호 통신 명령을 제거했지만 여전히 필요한 결과를 제공했습니다 – user2581707

+0

귀하의 답변을 기다리십시오. 잠금을 구현하고 인스턴스/정적 필드를 사용하기위한 훌륭한 아이디어를 나열했습니다. 나는 이것을 명심해야한다. 위대한 직장 감사합니다 남자 !! – user2581707