我应该同步监听器通知吗? [英] Should I synchronize listener notifications, or not?

查看:178
本文介绍了我应该同步监听器通知吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我总是非常犹豫要把我的锁公开,让它们公开。我总是试图将锁限制在我的实现中。不这样做,是一个死锁的秘诀,我相信。



我有以下课程:

  class SomeClass {
protected ArrayList< Listener> mListeners = new ArrayList< Listener>();

protected void addListener(Listener listener){
synchronized(mListeners){
mListeners.add(listener);
}
}

protected void removeListener(监听器监听器){
synchronized(mListeners){
mListeners.remove(listener);
}
}

...
}

当SomeClass想要通知他的听众时,你会这样做:

  synchronized(mListeners){
for(Listener l:mListeners){
l.event();
}
}

  Listener [] listeners = null; 

synchronized(mListeners){
listeners = mListeners.toArray();
}
for(Listener l:listeners){
l.event();
}

我会选择第二种选择。缺点是听众可以获得活动,即使他们已经取消注册。好处是,一个侦听器calllback正在等待的线程,当他想取消注册一个监听器时,它不会遇到死锁。我认为好处比下行路更重要,可以很容易地记录下来。



所以这里的问题基本上是:你会暴露你的锁吗? / p>

我的问题是,如果您选择普通的ArrayList,LinkedList,ConcurrentLinkedQueue,CopyOnWriteArrayList,......!您是否会介意侦听器是否可以在未注册时收到通知。无论你是否将锁打开,或不是。这是关于避免死锁。



请分享您的想法。谢谢!

解决方案

为侦听器数组使用 CopyOnWriteArrayList



这对于不经常更改的侦听器阵列非常适合。当您遍历它们时,您将遍历底层数组。使用 CopyOnWriteArrayList ,每次修改此数组时都会复制该数组。所以在迭代时不需要与它同步,因为每个底层数组都保证是静态的,甚至超过它在 CopyOnWriteArrayList 中的使用。



由于 CopyOnWriteArrayList 也是线程安全的,因此您无需同步add& amp;删除操作。



声明:

  private final CopyOnWriteArrayList< Listener>听众; 

事件触发器:

  for(Listener l:this.listeners){
l.event();
}


I am always very hesitant to bring my locks in the open, to make them public. I always try to keep the locks restricted to my implementation. Not doing that, is a recipe for deadlocks, I believe.

I have the following class:

class SomeClass {
    protected ArrayList<Listener> mListeners = new ArrayList<Listener>();

    protected void addListener(Listener listener) {
        synchronized (mListeners) {
            mListeners.add(listener);
        }
    }

    protected void removeListener(Listener listener) {
        synchronized (mListeners) {
            mListeners.remove(listener);
        }
    }

    ...
}

When SomeClass wants to notify his listeners, would you do:

    synchronized (mListeners) {
        for (Listener l : mListeners) {
             l.event();
        }
    }

or

    Listener[] listeners = null;

    synchronized (mListeners) {
        listeners = mListeners.toArray();
    }
    for (Listener l : listeners) {
        l.event();
    }

I would choose the second option. The downside is that listeners can get events, even though they are already unregistered. The upside is that a thread, on which a listener calllback is waiting, cannot run into a deadlock when he wants to unregister a listener. I believe the upside is way more important than the downside, which can be easily documented.

So the question here is basically: would you expose your lock, or not?

My question is NOT if you would choose a plain ArrayList, a LinkedList, a ConcurrentLinkedQueue, a CopyOnWriteArrayList, a ...! It is whether you would mind if a listener can get a notification while it is already unregistered. It is whether you would bring the lock in the open, or not. It's about avoiding deadlocks, or not.

Please share your thoughts. Thanks!

解决方案

Use a CopyOnWriteArrayList for your listener arrays.

This is perfect for listener arrays which change infrequently. When you iterate through them, you're iterating through the underlying array. With a CopyOnWriteArrayList, this array is copied every time it is modified. So there is no need to synchronize with it when iterating because each underlying array is guaranteed to be static, even past its use within the CopyOnWriteArrayList.

Since CopyOnWriteArrayList is also thread safe, you do not need to synchronize the add & remove operations.

Declaration:

private final CopyOnWriteArrayList<Listener> listeners;

Event trigger:

for (Listener l: this.listeners) {
  l.event();
}

这篇关于我应该同步监听器通知吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆