协程和 Java 同步不能混用

Posted 码农乐园

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了协程和 Java 同步不能混用相关的知识,希望对你有一定的参考价值。

先看一下测试代码

repeat(2) 
            thread  test() 
        
@Synchronized
    fun test() 
        println("Starting!")
        Thread.sleep(10)
        println("Ending!")
    

输出结果,没有交叉:

假设我们正在使用协程。那会发生什么?

val scope = CoroutineScope(Job())


        repeat(2) 
            thread  test() 
        
@Synchronized
    fun test() 
        println("Starting!")
        Thread.sleep(10)
        println("Ending!")
    

在这种情况下,临界区有交错调用

Starting!
Starting!
Ending!
Ending!

了解的是挂起函数实际上并不是逐行执行代码。当一个挂起函数到达一个挂起点时,它会停止该函数的执行并将控制权传递给另一个函数(要理解挂起函数将在稍后恢复)

因此,第二个代码示例中真正发生的是:test()开始,获得锁,打印出“开始!”

它到达delay()(这是一个暂停点),所以它退出函数并释放锁。

随着锁的释放,第二次执行test()开始,获取锁,挂起,释放锁。

当每个延迟完成时,test()再次调用(但在 之后的某个点delay())。

拥有临界区的唯一原因是共享可变状态。因此,我们要解决的真正问题是“我们需要一种控制共享可变状态的方法”。

val mutex = Mutex()
val scope = CoroutineScope(Job())


repeat(2) 
  scope.launch  testLocked() 



suspend fun testLocked() 
  mutex.withLock 
    println("Starting!")
    delay(10)
    println("Ending!")
  

使用synchronized函数但现在想使其暂停的情况下,Mutex是进行该转换的最自然方法.

以上是关于协程和 Java 同步不能混用的主要内容,如果未能解决你的问题,请参考以下文章

纯kotlin+ViewModel+LiveData+协程MVVM

python协程和异步IO——IO多路复用

进程线程协程和GIL

线程进程协程和GIL

gj12-1 协程和异步io

为你揭秘 Python 中的进程线程协程同步异步回调