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

如何用协程实现代码块串行执行(类似@synchronized效果)

协程实现文件操作串行执行的方案

你需要让BlockA、BlockB、BlockC三个文件操作串行执行,同一时间仅运行一个,这里有几个用协程实现的靠谱方式:

1. 使用单线程限制的Dispatcher

Kotlin 1.6及以上版本提供了limitedParallelism方法,可以把Dispatchers.IO的并行度限制为1,所有通过这个Dispatcher启动的协程都会串行执行——本质是复用IO线程池里的一个线程,很适合IO密集型操作。

代码示例:

// 定义单线程IO调度器
private val singleIODispatcher = Dispatchers.IO.limitedParallelism(1)
private val scope = CoroutineScope(Dispatchers.Main)

fun onReadClick() = scope.launch(singleIODispatcher) {
    blockA()
}

fun onSaveClick() = scope.launch(singleIODispatcher) {
    blockB()
}

fun onDeleteClick() = scope.launch(singleIODispatcher) {
    blockC()
}

2. 使用协程互斥锁Mutex

Mutex是协程版的synchronized,通过withLock方法包裹临界区代码,确保同一时间只有一个协程能执行这段逻辑,不管用什么Dispatcher都能生效,灵活性更高。

代码示例:

private val fileMutex = Mutex()
private val scope = CoroutineScope(Dispatchers.Main)

fun onReadClick() = scope.launch(Dispatchers.IO) {
    fileMutex.withLock {
        blockA()
    }
}

fun onSaveClick() = scope.launch(Dispatchers.IO) {
    fileMutex.withLock {
        blockB()
    }
}

fun onDeleteClick() = scope.launch(Dispatchers.IO) {
    fileMutex.withLock {
        blockC()
    }
}

3. 使用Channel作为任务队列

创建一个单消费的Channel,把每个文件操作作为任务发送到Channel中,再启动一个专门的协程循环接收任务并串行执行,适合需要动态添加任务或者批量处理的场景。

代码示例:

private val taskChannel = Channel<suspend () -> Unit>(Channel.UNLIMITED)
private val scope = CoroutineScope(Dispatchers.Main)

// 启动任务消费协程
init {
    scope.launch(Dispatchers.IO) {
        for (task in taskChannel) {
            task()
        }
    }
}

fun onReadClick() = scope.launch {
    taskChannel.send { blockA() }
}

fun onSaveClick() = scope.launch {
    taskChannel.send { blockB() }
}

fun onDeleteClick() = scope.launch {
    taskChannel.send { blockC() }
}

// 页面销毁时记得关闭Channel和协程
fun onDestroy() {
    taskChannel.close()
    scope.cancel()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 10:22:38