java - 在另一个线程读取 Java 列表引用时更改它

标签 java multithreading

我找不到这个问题的明确答案,因此,如果其他地方对此问题有很好的回答,我深表歉意。

想象一下我有大致类似的东西:

Class SomeClass
{
  List<String> strings = new LinkedList<>();


  public void updateList(List<String> newStrings) {
    strings = newStrings;
  }

  public List<String> getMatchingStrings(String pattern) {
    List<String> matches = new LinkedList<>();
    for (String s : strings) {
      if (matchesPattern(s, pattern)) { //Assume this just works
        matches.add(s);
      }
    }
    return matches;
  }

}

假设另一个线程调用 updateList(...)当某个线程正在调用getMatchingStrings()时,会不会有“问题”?

预期的行为是当前执行的线程 getMatchingStrings()将在旧列表上运行,后续调用将在更新后的列表上运行。

感谢任何帮助!

最佳答案

您的代码中存在“不安全发布”(写入列表字段和读取列表字段之间没有“发生在顺序之前”)。使用阻塞的“同步”或非阻塞的“ volatile ”或“原子引用”:

// with 'synchronized'
class SomeClass0 {
    List<String> strings = new LinkedList<>();

    public synchronized void updateList(List<String> newStrings) {
        this.strings = newStrings;
    }

    public synchronized List<String> getMatchingStrings(String pattern) {
        List<String> matches = new LinkedList<>();
        for (String s : strings) {
            if (matchesPattern(s, pattern)) { //Assume this just works
                matches.add(s);
            }
        }
        return matches;
    }
}

// with 'volatile'
class SomeClass1 {
    volatile List<String> strings = new LinkedList<>();

    public void updateList(List<String> newStrings) {
        this.strings = newStrings;
    }

    public List<String> getMatchingStrings(String pattern) {
        List<String> localCopy = this.strings;
        List<String> matches = new LinkedList<>();
        for (String s : localCopy) {
            if (matchesPattern(s, pattern)) { //Assume this just works
                matches.add(s);
            }
        }
        return matches;
    }
}

// with 'AtomicReference'
class SomeClass2 {
    AtomicReference<List<String>> strings = 
                        new AtomicReference<>(new LinkedList<>());

    public void updateList(List<String> newStrings) {
        this.strings.set(newStrings);
    }

    public List<String> getMatchingStrings(String pattern) {
        List<String> localCopy = this.strings.get();
        List<String> matches = new LinkedList<>();
        for (String s : localCopy) {
            if (matchesPattern(s, pattern)) { //Assume this just works
                matches.add(s);
            }
        }
        return matches;
    }
}

关于java - 在另一个线程读取 Java 列表引用时更改它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38086999/

相关文章:

java - 线程本地资源

java - 泛型方法重写其基础的泛型方法

java - 自动装箱前如何获取原始类型?

Java线程notify() wait()以加快计算速度

java - 主线程似乎没有被中断

multithreading - Node 后台线程 - 这些线程何时创建?

java - SEVERE : jdbcrealm. invaliduserreason WEB9102:Web 登录失败

java - Lucene TwoWayFieldBridge 慢查询

java websocket EOFException发生

c# - 为什么线程和任务之间的性能差异如此之大?