简体   繁体   English

我是否需要同步访问仅由一个线程修改的List?

[英]Do I need to synchronize access to a List that is only modified by one thread?

Here I have a class that has two threads that have access to a List. 这里我有一个类,它有两个可以访问List的线程。 One thread periodically replaces the list with an updated copy, and the other thread paints the list's contents onto the screen. 一个线程定期用更新的副本替换列表,另一个线程将列表的内容绘制到屏幕上。

public class ThreadSafePainter {
    private List<String> dataList = new ArrayList<>();

    /*
     *  starts a thread to periodically update the dataList
     */
    public ThreadSafePainter() {
        Thread thread = new Thread(() -> {
            while (true) {
                // replace out-dated list with the updated data
                this.dataList = getUpdatedData();
                // wait a few seconds before updating again
                Thread.sleep(5000);
            }
        });
        thread.start();
    }

    /*
     *  called 10 times/second from a separate paint thread
     *  Q: Does access to dataList need to be synchronized?
     */
    public void onPaint(Graphics2D g) {
        Point p = new Point(20, 20);

        // iterate through the data and display it on-screen
        for (String data : dataList) {
            g.drawString(data, p.x, p.y);
            p.translate(0, 20);
        }
    }

    /*
     *  time consuming data retrieval
     */
    private List<String> getUpdatedData() {
        List<String> data = new ArrayList<>();
        // retrieve external data and populate list
        return data;
    }
}

My question is, do I need to synchronize access to the dataList? 我的问题是,我是否需要同步访问dataList? How should I go about doing that? 我应该怎么做呢? Would this work: 这会工作:

public ThreadSafePainter() {
    ...
            synchronized (this) {
                this.dataList = getUpdatedData();
            }
    ...
}

public void onPaint(Graphics2D g) {
    ...
    synchronized (this) {
        for (String data : dataList)
            ...
    }
}

Any time you have more than one thread accessing the same mutable state (well, almost anytime, there are some exceptions, like when you know the state won't mutate within the other thread's lifetime), you need to take some type of action. 任何时候你有多个线程访问相同的可变状态(好吧,几乎任何时候,都有一些例外,比如当你知道状态不会在另一个线程的生命周期内变异时),你需要采取某种类型的操作。 In this case, you are mutating the field dataList and you expect another thread to react to this. 在这种情况下,您正在改变字段dataList并且您希望另一个线程对此作出反应。 So, you need to do "something". 所以,你需要做“某事”。 The most general solution is to use synchronized , and your outline of how to do this is just fine. 最通用的解决方案是使用synchronized ,你的大纲如何做到这一点就好了。

If you want to use squeeze maximum performance out of something (which is kind of ridiculous for a GUI problem), or you want to show off your great understanding of concurrency, you can consider more light-weight alternatives that apply to more limited circumstances. 如果你想使用某种东西来挤压最大性能(这对于GUI问题来说是一种荒谬的东西),或者你想展示你对并发性的深刻理解,你可以考虑更适合更有限环境的轻量级替代品。 In this case, you have only one writer, and the writer is only writing a single reference. 在这种情况下,您只有一个编写器,编写器只编写一个引用。 For such cases, volatile is sufficient. 对于这种情况, volatile就足够了。 In this kind of code, I would personally just stick to synchronized because it is less likely to break when you change the code, like perhaps you add another writer thread or something. 在这种代码中,我个人只是坚持synchronized因为当你更改代码时它不太可能破坏,就像你可能添加另一个编写器线程或其他东西。

If you do not make the list synchronized then you should make the List volatile. 如果您没有使列表同步,那么您应该使List易失。 This way the reading thread gets the latest copy of the List variable's value. 这样读取线程获取List变量值的最新副本。

Here is a good explanation. 是一个很好的解释。

The official Java-Documentation points out, that an ArrayList is not synchronized. 官方Java-Documentation指出,ArrayList未同步。 So you need to synchronize it. 所以你需要同步它。

However the documentation also says this applies only if multiple threads access the same list. 但是文档还说这只适用于多个线程访问同一个列表的情况。 So in your case it should not be necessary to synchronize it. 所以在你的情况下,没有必要同步它。 But if you want to be 100% sure you can synchronize your List with this simple call: 但是如果你想100%确定你可以通过这个简单的调用同步你的List:

List<data_type> list = Collections.synchronizedList(new ArrayList<data_type>());

...where "data_type" is the type values you want to store. ...“data_type”是您要存储的类型值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如果仅添加一个线程而仅删除一个(不同)线程,是否需要同步缓冲区? - Do you need to synchronize a buffer if only one thread adds and only one (different) thread removes? 如果只有一个编写器线程,我们是否需要同步java HashMap获取 - Do we need to synchronize java HashMap gets if there is only one writer thread 如果只有一个writer线程并且没有对映射进行结构修改,我们是否需要同步java HashMap获取 - Do we need to synchronize java HashMap gets if there is only one writer thread and no structural modifications to the map are done 如何同步缓存列表访问 - How do I synchronize cache list access 我需要同步吗 - Do I need Synchronize this 是否需要同步访问 Java 中的不可变类型? - Do I need to synchronize access to immutable types in Java? 仅在需要时添加密钥时是否需要同步ConcurrentMap? - Do I need to synchronize ConcurrentMap when adding key only if needed? 很多读者,一位作家:我需要同步吗? - Many Readers, one writer: Do i need to synchronize this? 为什么我需要同步Collections.synchronizedList返回的列表 - Why do I need to synchronize a list returned by Collections.synchronizedList 我需要同步 writeObject() 吗? - Do I need to synchronize writeObject()?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM