You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中迭代SynchronizedList子列表时应使用何种同步方式?

SynchronizedList子列表迭代的正确同步方式

问题背景

当通过Collections.synchronizedList()创建的同步列表调用subList()方法得到子列表后,迭代该子列表时需要采用何种同步方式?这是一个容易踩坑的线程安全问题。

官方文档的基础规则

根据Collections.synchronizedList()的官方文档说明,迭代同步列表时必须手动在该列表对象上进行同步,官方给出的示例如下:

List list = Collections.synchronizedList(new ArrayList());
// ...
synchronized (list) {
    Iterator i = list.iterator(); // 必须在同步块内执行迭代器创建与遍历
    while (i.hasNext())
        foo(i.next());
}

子列表的锁对象误区

但需要注意的是,SynchronizedList的子列表不会以自身作为互斥锁——从源码实现来看,子列表会复用原同步列表的锁对象。如果像下面这样直接对子列表对象加锁,属于错误的同步方式:

List subList = synchronizedList.subList(2, 5);
synchronized (subList) { // 错误:子列表并非实际的锁对象
    Iterator i = subList.iterator();
    while (i.hasNext())
        foo(i.next());
}

这种写法无法保证线程安全,因为其他线程操作原列表或子列表时,用的是原列表的锁,当前同步块的锁起不到互斥作用。

正确的同步方式

迭代子列表时,必须以原同步列表的对象作为锁,示例代码如下:

List originalSyncList = Collections.synchronizedList(new ArrayList());
List subList = originalSyncList.subList(2, 5);
// ...
synchronized (originalSyncList) { // 使用原同步列表作为锁对象
    Iterator i = subList.iterator();
    while (i.hasNext())
        foo(i.next());
}

文档的疏漏点

目前官方文档仅明确了原同步列表的迭代同步要求,并未提及子列表的这一特殊情况。这确实是文档的一处不足,因为开发者很容易按照惯性用子列表本身加锁,进而引发线程安全问题,建议官方文档补充这一细节说明。

内容的提问来源于stack exchange,提问作者peremeykin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 11:05:01