在对象监视器上同步或在我的情况下是一个更好的信号量?

时间:2016-09-10 19:02:48

标签: java android multithreading callback thread-safety

我怀疑我的方法是否是线程安全的,相反我确信它不是线程安全的,但我还没有找到解决方案。 以下是我的代码:

    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(final Listener listener)不是ThreadSafe。

我不想处理多个侦听器,而是必须确保调用方法isEnable(最终侦听器侦听器)的最后一个将收到回调。

但是如果有两个不同的线程调用isEnable(最终的监听器监听器),那么调用该方法的最后一个会收到两个监听器回调吗?

编辑:我想用这个推断的代码做什么:

  • 只有在尚未设置“status”变量的情况下才需要注册接收器 先前调用isEnable(最终的侦听器侦听器),为此我创建了一个“setted”变量,并在设置状态变量的同时将其设置为true。
  • 我使用synchronized来防止并发访问“setted”和“status”成员变量
  • 我想要做到这一点:

    线程A 在时间1调用:

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

    主题B在时间2做同样的事情

    我认为只有线程B接收监听器结果,我会阻止注册多个BroadcastREceiver,因为如果我做那个线程B接收两个具有相同结果的回调。

1 个答案:

答案 0 :(得分: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));
  }

  // ...
}

已编辑以阻止TestLockSingleton.isEnable在调用Listener.isEnable时持有锁定。在这种情况下,不清楚这是否可取。