2016-09-10 1 views
0

내 메서드가 스레드로부터 안전한지 또는 그 반대인지 의심 스러워요. 스레드로부터 안전하지는 않지만 확실히 해결책을 찾지 못했습니다. 개체 모니터 또는 내 경우에는 세마포어에 동기화 된?

class TestLockSingleton 
    { 
     private static TestLockSingleton ourInstance = new TestLockSingleton(); 
    public static TestLockSingleton getInstance() { 
     return ourInstance; 
    } 

    private TestLockSingleton() { 
    } 

    ... 
    private Object LockMonitor= new Object(); 

      interface Listener 
     { 
      void isEnable(boolean result); 
     } 

public void setStatus(int status){ 
    synchronized(LockMonitor){ 
     this.status = status; 
     this.setted = true; 
    } 
} 

     public void isEnable(final Listener listener){ 
      synchronized(LockMonitor){ 
       if(!setted){ 
        LocalBroadcastManager.getInstance(context).registerReceiver(new BroadcastReceiver() { 
        @Override 
        public void onReceive(Context context, Intent intent) { 
         synchronized(LockMonitor){ 
          Bundle bundle = intent.getExtras(); 
          setStatus(bundle.getInt("Status", OFFVALUE)); 
          Listener.isEnable((status==ACTIVEVALUE)?true:false); 
          LocalBroadcastManager.getInstance(context).unregisterReceiver(this); 
         } 
        } 
        },new IntentFilter(MYACTION)); 
       }else{ 
        Listener.isEnable((status==ACTIVEVALUE)?true:false); 
       } 
      } 

     } 
    .... 
    } 

지금 내 문제는 내가 TestLockSingleton 클래스 내부의 방법 isEnable (최종 리스너 리스너) 스레드 안전이 아니라고 생각한다는 것입니다 : 다음 내 코드입니다.

둘 이상의 수신기를 처리하고 싶지는 않지만 대신 마지막 메서드 인 isEnable (최종 리스너 수신기)을 호출 한 사람이 콜백을 수신하는지 확인해야합니다.

두 개의 다른 스레드가 isEnable (최종 리스너 수신기)를 호출하면 메소드를 호출 한 마지막 수신기는 두 개의 수신기 콜백을 수신합니까?

편집 : 나는 "상태"변수가 이미 isEnable에 선행 호출에서 잘 살고 있지 않은 경우에만 수신기 (최종 리스너 리스너를) 등록 할

  • :이 그렇게하고 싶지는 무엇 코드를 추정 그렇게하기 위해서 나는 "setted"변수를 만들고 이것을 상태 변수를 설정하는 것과 동시에 true로 설정했습니다.

     TestLockSingleton.getInstance().isEnable(
          new Listener() 
        { 
           @Override 
         public void isEnable(boolean result) { 
    
         } 
        }) 
    

    :

    시간에서 1 호출을 스레드 :

  • 내가 이것을 달성하려면 "걸렸고"및 "상태"멤버 변수
  • 동시 액세스를 방지하기 위해 동기화 사용하십시오 스레드 B는 시간 2에 똑같은 작업을 수행합니다.

    나는 스레드 B가 리스너 resu 왜냐하면 나는 그 스레드 B가 두 개의 콜백을 동일한 결과로 수신하기 때문에, 하나 이상의 BroadcastReceiver를 등록하는 것을 막을 것이다.

+1

성취하려는 것을 말할 수 있습니까? 이 코드는 그대로 컴파일되지 않습니다. 특정 시점에 둘 이상의 브로드 캐스트 수신기가 설치되지 않도록 동기화를 사용하려고합니까? –

+0

안녕하세요. 내 질문을 읽어 주셔서 감사합니다. 내 하찮은 영어 실력에 죄송하다는 말씀을 드리고 싶습니다. 나는 더 많은 설명과 함께 첫 번째 메시지를 편집했다. 이 코드는 실제 코드의 faqsimile이기 때문에 컴파일되지 않습니다. – aeroxr1

답변

1

아래와 같은 코드가 필요하다고 생각합니다.

주의해야합니다. Listener.isEnable은 복수 스레드에서 호출됩니다. TestLockingSingleton.isEnable을 호출하는 스레드와 주 스레드입니다.

public class TestLockSingleton { 
    // ... 

    public interface Listener { 
    void isEnable(boolean isActive); 
    } 

    private static TestLockSingleton instance = new TestLockSingleton(); 

    public static TestLockSingleton getInstance() { 
    return instance; 
    } 


    private final Object lock = new Object(); 
    private int status; 
    private boolean enabled; 

    private TestLockSingleton() { 
    } 

    public void setStatus(int status) { 
    synchronized (lock) { 
     this.status = status; 
     this.enabled = true; 
    } 
    } 

    public void isEnable(Context context, final Listener listener) { 
    boolean enabled; 
    boolean active; 
    synchronized (lock) { 
     enabled = this.enabled; 
     active = status == ACTIVEVALUE; 
    } 

    if (enabled) { 
     listener.isEnable(active); 
     return; 
    } 

    LocalBroadcastManager.getInstance(context).registerReceiver(
     new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      int status = intent.getExtras().getInt("Status", OFFVALUE); 
      setStatus(status); 
      listener.isEnable(status == ACTIVEVALUE); 
      LocalBroadcastManager.getInstance(context).unregisterReceiver(this); 
     } 
     }, 
     new IntentFilter(MYACTION)); 
    } 

    // ... 
} 

편집 :Listener.isEnable를 호출하는 동안 잠금을 보유에서 TestLockSingleton.isEnable을 방지합니다. 이 경우에 이것이 바람직한 지 명확하지 않다.

+0

광산처럼이 방법은 주어진 시간에 둘 이상의 방송 수신기가 등록되는 것을 방지하지 않습니까, 아니면 제가 틀렸습니까? 스레드 B는 불행한 경우에 리스너의 두 콜백을 수신 할 수 있습니다. 하나는 thread A가 등록한 broadcastReceiver에서, 하나는 자체적으로 등록한 broadcastReceiver에 등록 되었습니까? 아니면 틀렸습니까? – aeroxr1

+1

당신과 나의 어느 누구도 한 번에 하나의 BroadcastReceiver 만 등록 할 것을 보장하지 않습니다. 그렇게하고 싶다면'this.enabled'를 사용하여 Receiver가 등록되었음을 표시해야합니다. BroadcastReceiver를 영구적으로 등록하는 것을 고려했으며 0 명 또는 1 명의 청취자 만 등록 할 수 있습니까? –

+0

예 처음에는 그런 식으로 생각했지만 상태 값이 도착했을 때 수신기를 등록 취소하는 것이 중요합니다. 어떻게 마지막 수신자에게만 저항을 허용 할 수 있습니까? – aeroxr1