Kotlin 中的并发与多线程:高级水平

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Kotlin 中的并发与多线程:高级水平

\n

在现代 Kotlin 开发中,尤其是对于服务器端和 Android 应用程序,良好的并发管理是性能和响应能力的关键。在高级水平上,仅仅启动一个协程是不够的。需要理解如何有效地同步数据访问、管理线程以及避免“地狱般的”锁。在本文中,我们将深入探讨高级技术:从 kotlinx.coroutines 的细微之处到线程安全集合和通道。

\n\n

1. 深入理解协程:结构化并发与作用域

\n

高级工作的基础是 结构化并发。这是一个原则,即协程的生命周期绑定到其作用域。如果父协程被取消,其所有子任务将自动终止。这可以防止内存泄漏和不受控制的进程。

\n

在高级水平上,您应该创建自己的作用域,而不是依赖全局的 GlobalScope。

\n\n
import kotlinx.coroutines.*\nimport kotlin.coroutines.CoroutineContext\n\nclass DataRepository {\n    // 自定义作用域,包含调度器和异常处理器\n    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob() + CoroutineExceptionHandler { _, throwable ->\n        println("未处理的错误:${throwable.message}")\n    })\n\n    fun loadData() {\n        scope.launch {\n            // 子协程\n            val data = async { fetchFromNetwork() }\n            val cache = async { loadFromCache() }\n            process(data.await(), cache.await())\n        }\n    }\n\n    fun cleanup() {\n        scope.cancel() // 取消作用域中的所有协程\n    }\n}
\n\n

当一个子协程的失败不应取消其他协程时,请使用 SupervisorJob。这对于 UI 层或并行的独立请求至关重要。

\n\n

2. 线程安全集合与原子操作

\n

即使使用协程,如果您处理共享的可变数据,也需要同步。Kotlin 提供了几种方法:

\n
    \n
  • 原子类型(AtomicInteger、AtomicReference)——用于简单的计数器和标志。
  • \n
  • 线程安全集合(ConcurrentHashMap、CopyOnWriteArrayList)——用于复杂的数据结构。
  • \n
  • Mutex 来自 kotlinx.coroutines ——用于协程内部的临界区。
  • \n
\n\n
import kotlinx.coroutines.*\nimport kotlinx.coroutines.sync.Mutex\nimport kotlinx.coroutines.sync.withLock\nimport java.util.concurrent.ConcurrentHashMap\nimport java.util.concurrent.atomic.AtomicInteger\n\nclass SafeCounter {\n    private val mutex = Mutex()\n    private var counter = 0\n\n    suspend fun increment() {\n        mutex.withLock {\n            counter++ // 临界区\n        }\n    }\n\n    fun getCounter(): Int = counter\n}\n\nclass CacheManager {\n    private val cache = ConcurrentHashMap<String, String>()\n    private val hitCount = AtomicInteger(0)\n\n    fun put(key: String, value: String) {\n        cache[key] = value\n    }\n\n    fun get(key: String): String? {\n        val result = cache[key]\n        if (result != null) hitCount.incrementAndGet()\n        return result\n    }\n}
\n\n

重要:Mutex 是一个挂起函数,因此它不会阻塞线程,而是挂起协程。这比 synchronized 更高效。

\n\n

3. 通道 (Channels) 和 Flow:响应式数据流

\n

为了在协程之间传输数据,请使用 Channels(协程版的 BlockingQueue)和 Flow(冷异步流)。

\n\n

通道:生产者-消费者

\n
import kotlinx.coroutines.channels.*\nimport kotlinx.coroutines.*\n\nfun Corout                

博客

书籍推荐