0

다음 프로그램은 스핀 루프로 끝납니다. 나는 그 이유가 무엇인지 모릅니다. 누군가가 나를 도울 수 있다면 나는 행복 할 것입니다. 다음 코드에서는 그룹 224.0.1.20:64의 수신자에게 일부 데이터를 멀티 캐스트하는 보낸 사람이 있습니다. 보낸 사람은 val 개체의 변수 rr1ThreadManager 클래스 인 데이터를 보내기를 기다립니다. 마치기 전에 동일한 인스턴스의 val1이 변경 될 때까지 기다린 후 닫힙니다. 전에 join()을 시도했습니다. 그러나 그것도 작동하지 않았다. 아래에서 볼 수 있듯이 보낸 사람은 다음과 같이 기다립니다. 코드가 올바르게 실행되어 출력되는 경우도 있지만 반복되는 경우도 있습니다. 가는
1. :멀티 캐스트 중 프로그램 스핀

package com.test; 

import java.io.IOException; 
import java.net.DatagramPacket; 
import java.net.InetAddress; 
import java.net.MulticastSocket; 
import java.util.Date; 

public class Test { 
    public static void main(String[] args) throws IOException, InterruptedException { 
     Sender s = new Sender(64); 
     ThreadManager r = new ThreadManager(); 
     ThreadManager r1 = new ThreadManager(); 
     r.start(); 
     r1.start(); 
     //Thread.currentThread().setPriority(1); 
     while(r.val1 != true || r1.val1 != true){ 
        >// I know this is wrong way to wait, but this is just a test 
        >// appln, so I used polling. 
      //Thread.currentThread().sleep(1); 
      //System.out.println(r.val1 || r1.val1); 
     } 
     System.out.println("going to send.."); 
     s.send("kaushik"); 
     while((r.val != true || r1.val != true) || (r.isAlive() && r1.isAlive())){ 
        // same here.. 
      System.out.println(r.val || r.val1); 
      //Thread.sleep(1000); 
     } 
     System.out.println("closing.."); 

    } 
} 
class ThreadManager extends Thread{ 
    public boolean val = false; 
    public boolean val1 = false; 
    @Override 
    public void run() { 
     // TODO Auto-generated method stub 
     Reciever r; 
     try { 
      r = new Reciever(64); 

      byte[] buf = new byte[65508]; 
      System.out.println("Going. to be started..."); 
      DatagramPacket packet = new DatagramPacket(buf, 65508); 
    val1 = true; 

      r.recieve(packet); 

     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

      val = true; 
      System.out.println(val+" Id :"+Thread.currentThread().getId()); 


    } 

} 
class Sender{ 
    private MulticastSocket s; 
    public Sender(int port) throws IOException{ 
     s = new MulticastSocket(port); 
     s.joinGroup(InetAddress.getByName("224.0.1.20")); 
    } 
    public void send(String data) throws IOException{ 
     System.out.println("Server"+s.getLocalPort()); 
     DatagramPacket packet = new DatagramPacket(data.getBytes(), data.getBytes().length,InetAddress.getByName("224.0.1.20"),s.getLocalPort()); 
     s.send(packet); 
     System.out.println("server"+s.getRemoteSocketAddress()); 
     s.close(); 
    } 
} 
class Reciever{ 
    private MulticastSocket s; 
    public Reciever(int port) throws IOException{ 
     s = new MulticastSocket(port); 
     s.joinGroup(InetAddress.getByName("224.0.1.20")); 
    } 
    public void recieve(DatagramPacket packet) throws IOException{ 
     s.receive(packet); 
     byte recv[] = new byte[65508]; 
     System.arraycopy(packet.getData(), 0, recv, 0, packet.getData().length); 
     //System.out.println(new String(recv)); 
     System.out.println(new String(recv).trim() + "Date : "+ new Date() + "length :" +new String(recv).trim().length()); 
     s.leaveGroup(InetAddress.getByName("224.0.1.20")); 
     s.close(); 
    } 
} 

출력. 시작할 수 있습니다 ...
Going. 시작하기 ...
보내려고 ..
Server64
servernull
kaushikDate : 수요일 11월 26일 동부 표준시 11시 19분 9초 2014length : 7
진정한 ID : 9
kaushikDate : 수요일 11월 26일 11 : 19:09 미국 중부 표준시 2014length : 7
사실 ID : 10

** pls 참조하십시오, 나는 ThreadManager 클래스 **에서 val1과 val을 true로 설정합니다. 위 출력에서 ​​val1은 r1 및 r 인스턴스 모두에 대해 true로 설정되었지만 여전히 프로그램이 종료되지 않습니다.

+0

교착 상태가 아닙니다. *** 블록, *** (receive)에 ***. 교착 상태는 순환 리소스 요청 패턴이있을 때 발생합니다. 그런 건 없어. – EJP

+0

@EJP : 때로는 "보낼 것입니다 .."교착 상태가 있음을 분명하게 나타내는이 줄이 인쇄되지 않습니다. 기본적으로, s.send ("kaushik")조차도; 호출이 호출되면 교착 상태가 발생하고 있습니다. –

+0

일부 코드 행에 도달하지 않으면 '교착 상태가 명확하게 나타남'을 나타내지 않습니다. 그것은 다른 많은 것들이 될 수 있습니다. 이 용어를 오용하고 있습니다. 봐봐. 여전히 교착 상태라고 생각되면 두 개 이상의 잠금 가능 자원이 관련되어 있는지 알려주십시오. – EJP

답변

2

교착 상태가 아닙니다. UDP은 신뢰할 수 없습니다. 팩이 길을 잃으면 수신자가 데이터를 기다리고 "교착 상태"처럼 보입니다. Reciever에 대해 "시간 초과"를 설정하는 것이 좋습니다.

여기에서 주 스레드와 r.val1을 공유하면 값이 변경 될 때 val1이 주 스레드에 즉시 표시되도록하려면 "volatile"이 필요합니다. 휘발성도 JIT 또는 CPU의 공격적인 최적화를 방지합니다. 즉, (R) 동기화 (R1)를 동기화 의미하기 때문에

public volatile boolean val1 = false; 

이 작동하지 않습니다 (이) 여기 동기화 동기화 사용의주의, 사람들은 다른의 "잠금". 스레드간에 공유 변수를 보호하려면 동일한 "잠금"을 사용하십시오.

+0

때로는 ** "보내려는 중 .."**이 줄은 인쇄되지 않고 교착 상태가 있음을 분명하게 나타냅니다. 기본적으로 ** s.send ("kaushik"); ** 호출이 호출되기 전에 교착 상태가 발생합니다 .. –

+0

@KaushikSivaprasad 아니요, 이전 루프에서 테스트중인 변수 이탈 값을 가정하지 마십시오. – EJP

+0

@EJP : 더 자세히 설명 할 수 있습니까? 고맙습니다. –