synchronized → Coroutines
老写法(Java --- synchronized 死锁)
scss
// 线程 A
synchronized (lockA) {
Thread.sleep(100);
synchronized (lockB) {
// 同时持有 lockA 和 lockB
}
}
// 线程 B
synchronized (lockB) {
Thread.sleep(100);
synchronized (lockA) {
// 同时持有 lockB 和 lockA --- 和线程 A 相反顺序,死锁
}
}
问题在哪里
多个 synchronized 嵌套且获取锁的顺序不一致时,两个线程互相等待对方释放锁,形成死锁。JVM 不会自动检测和解决死锁,APP 直接卡死。
Android 中的常见死锁场景:主线程等待子线程结果 + 子线程等待主线程释放资源。
新写法(Kotlin Coroutines)
kotlin
// 协程结构化并发 --- 避免锁竞争
suspend fun loadBoth() = coroutineScope {
val resultA = async { loadA() }
val resultB = async { loadB() }
Result(resultA.await(), resultB.await())
}
// 需要用锁时 --- Mutex.withLock 有超时
private val mutexA = Mutex()
private val mutexB = Mutex()
suspend fun safeOperation() {
mutexA.withLock {
mutexB.withLock {
// 两个锁都获取到了
}
}
}
一句话注意
协程的结构化并发是避免死锁的最佳方案------coroutineScope 保证并发任务全部完成或全部取消,不存在互相等待的锁依赖。async { } 启动子协程,await() 等待结果,整个过程不需要手动锁。
如果协程里确实需要锁,优先用单线程调度器(Dispatchers.Main + Dispatchers.IO 明确切换)消除竞争条件,而不是引入锁。最后的选择才是 Mutex------但用它时一定要保证加锁顺序一致。
Java Android 老项目迁移系列,持续更新中。