2017-03-13 3 views
1

두 개의 스레드가 있습니다. 하나는 짝수를 인쇄하고 다른 하나는 홀수를 인쇄합니다. 아래 사용자 지정 잠금의 도움으로 순서대로 번호를 인쇄하고 싶습니다. 문제는 일부 숫자를 인쇄 한 후 (표시된 숫자가 올바른 순서로 있음) 스레드가 교착 상태에 빠져있는 것입니다. 문제가 발견되지 않으면 1 시간 이상을 보냈습니다. 모든 것이 잘된 것처럼 보입니다.두 개의 스레드를 사용하여 순서대로 사용자 정의 잠금 인쇄 번호를 사용하면 다른 하나가 인쇄해도 홀수가됩니다.

public class Main{ 
     public static void main(String[] args){ 
      Lock lock=new Lock(); 
      SharedData sharedData=new SharedData(lock); 

      Thread th1=new Thread(new EvenWriter(sharedData)); 
      Thread th2=new Thread(new OddWriter(sharedData)); 

      th1.start(); 
      th2.start(); 
     } 
    } 
    class SharedData{ 
     Lock lock; 
     boolean printOdd; 
     SharedData(Lock lock){ 
      this.lock=lock; 
      this.printOdd=true; 
     } 
    } 
    class OddWriter implements Runnable{ 
     SharedData sharedData; 
     int num; 
     Lock lock; 
     public OddWriter(SharedData sharedData){ 
      this.sharedData=sharedData; 
      this.num=1; 
      this.lock=sharedData.lock; 
     } 
     public void run(){ 
      while(true){ 
      if(sharedData.printOdd){ 
       lock.lock(); 
       System.out.println(num); 
       num=num+2; 
       sharedData.printOdd=false; 
       lock.unlock(); 
      } 
      } 
     } 
    } 
    class EvenWriter implements Runnable{ 
     SharedData sharedData; 
     int num; 
     Lock lock; 
     public EvenWriter(SharedData sharedData){ 
      this.sharedData=sharedData; 
      this.num=2; 
      this.lock=sharedData.lock; 
     } 
     public void run(){ 
      while(true){ 
      if(!sharedData.printOdd){ 
       lock.lock(); 
       System.out.println(num); 
       num=num+2; 
       sharedData.printOdd=true; 
       lock.unlock(); 
      } 
      } 
     } 
    } 
    class Lock{ 

     private boolean locked=false; 
     public synchronized void lock(){ 

      while(locked){ 
       try{ 
       wait(); 
       } 
       catch(Exception e){ 
        e.printStackTrace(); 
       } 
      } 

      locked=true; 
     } 
     public synchronized void unlock(){ 
      locked=false; 
      try{ 
       notifyAll(); 
      } 
      catch(Exception e){ 
       e.printStackTrace(); 
      } 
     } 
    } 
+0

는'printOdd'이 volatile''할 필요가 사용 할 수 있습니다. – shmosel

+0

감사합니다. 휘발성 문제를 해결했습니다. 이유는 스레드가 주 메모리에서가 아닌 CPU 캐시에서 데이터를 읽었 기 때문에 발생했습니다. – Nishat

답변

0

당신은 printOddvolatile, 예를해야

class SharedData{ 
    Lock lock; 
    volatile boolean printOdd; 
    SharedData(Lock lock) { 
     this.lock=lock; 
     this.printOdd=true; 
    } 
} 

이것은 복수 스레드에서 printOdd을 사용하기 때문입니다. volatile의 목적은 모든 스레드가 메모리 조각에 액세스 할 수 있도록하는 것입니다. 이전에 액세스했던 첫 번째 스레드이기 때문에 전에 스레드에 printOdd의 액세스를 허용하고있었습니다.

-1

두 스레드간에 공유되는 데이터는 원자 적이어야합니다. 여기에 귀하의 경우에는 boolean printOdd이 교착 상태의 원인 인 스레드간에 공유됩니다. 당신은

AtomicBoolean printOdd;

+0

AtomicBoolean 클래스는 내부적으로 volatile int를 사용합니다. 나는 downvote의 이유가 무엇인지 모르겠다. –

+0

원자력은이 문제와 관련이 없습니다. – shmosel