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

Kotlin是否有Java Collections.synchronizedList等效实现?如何实现线程安全List?

Kotlin线程安全List实现指南

首先直接给你结论:Kotlin标准库中的可变列表(比如mutableListOf()默认返回的ArrayList)本身并不是线程安全的。原因很简单——Kotlin的集合框架大多直接复用Java的实现,mutableListOf()底层就是Java的java.util.ArrayList,而这个类没有任何线程同步机制,多线程环境下同时读写会导致数据不一致甚至抛出ConcurrentModificationException。

接下来给你几种实用的实现线程安全List的方案:

1. 用Java同步集合快速包装

Java的Collections.synchronizedList()可以把普通可变列表一键包装成线程安全版本,Kotlin里可以直接调用:

import java.util.Collections

val threadSafeList = Collections.synchronizedList(mutableListOf<String>())

⚠️ 注意:这个包装后的列表,迭代操作需要手动加锁,因为synchronizedList只保证单个方法的原子性,迭代是多个方法调用的组合(比如hasNext()+next()),不加锁会有并发问题。正确的迭代方式:

synchronized(threadSafeList) {
    threadSafeList.forEach { item ->
        // 处理每个元素
    }
}

2. 使用CopyOnWriteArrayList(读多写少场景首选)

如果你的业务是读操作远多于写操作,java.util.concurrent.CopyOnWriteArrayList是更优选择。它的核心逻辑是:每次写操作(添加、删除、修改)都会复制一份底层数组,读操作完全无锁,性能极高。Kotlin里直接实例化即可:

import java.util.concurrent.CopyOnWriteArrayList

val threadSafeList = CopyOnWriteArrayList<String>()

它的优势是迭代时不需要加锁,因为迭代的是当前数组的快照,不会抛出并发修改异常,非常适合频繁读取、偶尔修改的场景。

3. 自定义线程安全列表(适合定制需求)

如果需要更灵活的控制(比如只同步特定操作、用更高效的锁),可以自己封装一个线程安全的List类,利用Kotlin的委托特性减少重复代码:

import java.util.concurrent.locks.ReentrantLock
import java.util.concurrent.locks.Lock

class ThreadSafeMutableList<T> private constructor(
    private val delegate: MutableList<T>,
    private val lock: Lock = ReentrantLock()
) : MutableList<T> by delegate {

    companion object {
        fun <T> create(baseList: MutableList<T> = mutableListOf()): ThreadSafeMutableList<T> {
            return ThreadSafeMutableList(baseList)
        }
    }

    override fun add(element: T): Boolean {
        lock.lock()
        return try {
            delegate.add(element)
        } finally {
            lock.unlock()
        }
    }

    override fun remove(element: T): Boolean {
        lock.lock()
        return try {
            delegate.remove(element)
        } finally {
            lock.unlock()
        }
    }

    // 覆盖所有可变操作,比如addAll、removeAt、clear等,都用锁包裹
    override fun clear() {
        lock.lock()
        try {
            delegate.clear()
        } finally {
            lock.unlock()
        }
    }
}

这个方案可以根据业务需求选择锁的类型(比如公平锁、读写锁),或者只同步你需要的操作,灵活性拉满。

额外补充:不可变集合的线程安全

如果你的业务场景不需要修改集合内容,Kotlin的kotlinx.collections.immutable库提供的不可变集合本身就是线程安全的——因为不可变集合的状态一旦创建就不会改变,多线程读取完全没有问题。比如:

import kotlinx.collections.immutable.immutableListOf

val immutableList = immutableListOf("item1", "item2")

不过如果需要频繁修改,还是得用前面的可变线程安全方案。

内容的提问来源于stack exchange,提问作者A.Sanchez.SD

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:23:49