多线程环境中的Java列表

问题描述 投票:0回答:1

我想将以下代码转换为适合多线程环境的代码。

List<Observer> list = new ArrayList<>();

public void removeObserver(Observer p) {
    for (Observer observer: list) {
        if (observer.equals(p)) {
            list.remove(observer);
            break; 
        }
    }
}

public void addObserver(Observer p) {
    list.add(p);
}

public void notifyObserver(Event obj) {
    for (Observer observer: list) {
        observer.notify(obj);   
    }
}

无疑,最简单的方法之一是添加synchronized关键字,该关键字确保只有一个线程可以运行该逻辑,从而确保结果正确。

但是,有没有更好的方法来解决此问题。我进行了某种研究,发现可以使用Collections.synchronizedList,并且还注意到这样的list.iterator is not thread-safe,因此应避免直接使用forEach循环或迭代器unless I do a synchronized (list)我只是不想使用同步,并考虑是否还有另一种可能的方法。这是我的第二次尝试。

synchronized (list)

我只想问一下我的第二次尝试是否是线程安全的?另外,有没有比我提议的第二种方法更好的方法呢?

java multithreading list synchronized
1个回答
0
投票

当然,最简单的方法之一是添加synced关键字,这确保只有一个线程可以运行逻辑,从而确保结果正确。

这是正确的。

但是,有没有更好的方法来解决此问题?

我不这么认为。

让我们看看您的第二次尝试:

List<Observer> list = Collections.synchronizedList(new ArrayList<Observer>()); // which is thread safe

public void removeObserver(Observer p) {
    // as the list may get modify, I create a copy first
    List<Observer> copy = new CopyOnWriteArrayList(list);
    for (Observer observer: copy) {
        if (observer.equals(p)) {
            // but now, no use of iterator
            list.remove(observer); // remove it from the original copy
            break;
        }
    }
}

public void addObserver(Observer p) {
    list.add(p);
}

public void notifyObserver(Event obj) {
    List<Observer> copy = new CopyOnWriteArrayList(list); 
    // not use iterator, as thread safe list's iterator can be thread unsafe
    // and for-each loop use iterator concept
    for (Observer observer: copy) {
        observer.notify(obj);
    }
}

是的,它是线程安全的。有一定限制。

List<Observer> list = Collections.synchronizedList(new ArrayList<Observer>()); 
       // which is thread safe

这里有三个问题:

  1. 您正在创建列表的副本。这是一个public void removeObserver(Observer p) { // as the list may get modify, I create a copy first List<Observer> copy = new CopyOnWriteArrayList(list); ... 操作。

  2. O(N)构造函数将迭代CopyOnWriteArrayList ...,并且由list创建的列表的迭代不是原子/线程安全的,因此您具有竞争条件。

  3. synchronizedList相对于CopyOnWriteArrayList没有实际好处。 ArrayList对象是本地的并且是线程限制的,因此它不必是线程安全的。

总之,这不是线程安全的,仅使原始方法同步就更昂贵。

(我正在研究可能的改进。我会回到这个问题。)

© www.soinside.com 2019 - 2024. All rights reserved.