如何用协程实现代码块串行执行(类似@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
相关产品推荐
相关产品推荐

