java - 在对象监视器上同步还是在我的情况下是更好的信号量?

标签 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(final Listenerlistener) 的人会收到回调。

但是如果两个不同的线程调用 isEnable(final Listenerlistener) ,最后一个调用该方法的线程将收到两个监听器回调?

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

  • 仅当“状态”变量尚未从 先例调用 isEnable(final Listener Listener),为此,我创建了一个“已设置”变量,并在设置状态变量的同时将其设置为 true。
  • 我使用synchronized来防止并发访问“setted”和“status”成员变量
  • 我想完成这个:

    线程 A 在 1 次调用时:

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

    线程 B 在时间 2 做同样的事情

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

最佳答案

我认为您想要类似下面的代码。

你必须要小心。 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 时保持锁定。不清楚在这种情况下这是否是可取的。

关于java - 在对象监视器上同步还是在我的情况下是更好的信号量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39429573/

相关文章:

android - fragment 中的静态数组适配器。好的还是坏的做法?

java - 等待和通知的代码执行顺序

c++ - 在 For 循环 C++ 中创建线程

java - SWI-Prolog 接口(interface)中的 CLPFD 与 Java

java - 空 jface 窗口上出现奇怪的分隔符

java - 使用 DOM 解析器将 XML 文件输出到文本文件?

android - 我需要帮助在我的 mac m1 上的 android studio 中打开我的设备管理器

android - 选择 SMS、WhatsApp 或 Telegram 发送消息

multithreading - 优雅结束线程的必要性

java - 使用 spring-java-config 创建一个 'decider-step-loop'