java - 多线程环境下 LinkedList<T> clear 和 new LinkedList<T> 的区别

标签 java multithreading

为什么这段代码:

public synchronized void update() {
        for(T event : eventQueue)
        {
            processEvent(event);
        }
        events = eventQueue;
        eventQueue = new LinkedList<T>();
}

以不同方式运行此代码:

public synchronized void update() {
            for(T event : eventQueue)
            {
                processEvent(event);
            }
            events = eventQueue;
            eventQueue.clear();
}

第一个版本工作得很好,但第二个版本不行。 eventQueue.clear();导致应用程序不接收任何事件并以 Concurrent Exception 严重崩溃.

我的应用有两个线程。 UI线程和GameLoop线程。 UI 线程将事件添加到 eventQueue像这样:

public synchronized void addEvent(T newEvent) {
            eventQueue.add(newEvent);
}

GameLoop 线程调用更新方法来获取 events 的副本(称为 eventQueue ) .

所有代码都可以在这个网站查看:http://entropyinteractive.com/2011/02/game-engine-design-input/

这对我来说有点神秘,因为我认为 eventQueue = new LinkedList<T>();eventQueue.clear();都会导致空的 LinkedList ?我相信它与建立新引用有关(但为什么呢?!)。

最佳答案

因为在这段代码中:

public LinkedList<T> getEvents()
{
    return events;
}

您返回的是原始列表,而不是副本。如果您随后 clear() 该列表,您将导致问题,因为您正在从列表中删除内容(更重要的是,更改列表的大小),而另一个线程正在使用它。

请注意,此函数不是同步,因此您甚至无法安全地从中返回一个副本,因为原始列表可能会在您复制它时更改(更改引用为 atomic ,因此在您的 update() 方法中这样做是安全的。

您可以从同步方法返回一个副本,如下所示:

public synchronized LinkedList<T> getEvents()
{
    return new LinkedList<T>(events);
}

但这引入了不必要的复制和锁定。这是否重要取决于您是否更关心 defensive coding 或性能要求。我假设他们出于性能原因这样做。

关于java - 多线程环境下 LinkedList<T> clear 和 new LinkedList<T> 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15688367/

相关文章:

java - 我可以访问不在 Struts 2 ValueStack 上的另一个操作的属性吗?

java - 线程回调未调用。为什么?

c - 如何在单个CPU的多个CPU核心而不是多个CPU上设置亲和性?

c++ - 如何修复 C++ 线程死锁示例

java - 如何从源文件中提取JavaDoc注释

java - 在不扩展的情况下在 JFrame 上绘画

java - 等待webview中的javascript完成以继续Android Java

java - 作为字符串返回的 URL 在 JSF 中无效

java - 如何处理不停止线程的行为不当的库

c# - 在后台使用非托管库时无法更新 WPF GUI