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

Wil*_*ill 9 java multithreading paint thread-synchronization

这里我有一个类,它有两个可以访问List的线程.一个线程定期用更新的副本替换列表,另一个线程将列表的内容绘制到屏幕上.

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,我是否需要同步访问dataList?我应该怎么做呢?这会工作:

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

public void onPaint(Graphics2D g) {
    ...
    synchronized (this) {
        for (String data : dataList)
            ...
    }
}
Run Code Online (Sandbox Code Playgroud)

Mik*_*eVe -1

官方 Java 文档指出,ArrayList 不是同步的。所以你需要同步它。

然而,文档还说这仅适用于多个线程访问同一列表的情况。因此,在您的情况下,不需要同步它。但如果你想 100% 确定,你可以通过这个简单的调用来同步你的列表:

List<data_type> list = Collections.synchronizedList(new ArrayList<data_type>());
Run Code Online (Sandbox Code Playgroud)

...其中“data_type”是您要存储的类型值。

  • 该文档具有误导性。即使列表不需要同步,您也需要以安全的方式发布对列表的引用。 (5认同)