美文网首页js css html
kotlin<第十二篇>:协程并发安全

kotlin<第十二篇>:协程并发安全

作者: NoBugException | 来源:发表于2023-02-25 23:42 被阅读0次
(1)不安全的并发访问

我们使用线程在解决并发问题的时候总是会遇到线程安全的问题,而Java平台上的Kotlin协程实现免不了存在并发调度的情况,因此线程安全同样值得留意。

runBlocking {

    var count = 0
    List(1000) {
        GlobalScope.launch { count++ }
    }.joinAll()
    println(count)

}

打印出来的count值并不是1000。

(2)协程并发安全

在Java中,提供了原子性的对象:AtomicInteger,可以保证协程的安全性:

runBlocking {
    var count = AtomicInteger(0)
    List(1000) {
        GlobalScope.launch { count.incrementAndGet()}
    }.joinAll()
    println(count)
}

除了我们在线程中常用的解决并发问题的手段之外,协程框架也提供了一些并发安全工具,包括:

  • Channel:并发安全的消息通道;
  • Mutex:轻量级锁,它的lock和unlock从语义上与线程锁比较类似,之所以轻量级是因为它在获取不到锁时不会阻塞线程,二十挂起等待锁的释放。
  • Semaphore:轻量级信号量,信号量可以有多个,协程在获取到信号量后即可执行并发操作。当Semaphore的参数为1时,效果等价于Mutext。

Mutex演示:

runBlocking {
    var count = 0
    val mutex = Mutex()
    List(1000) {
        GlobalScope.launch {
            mutex.withLock { count++ }
        }
    }.joinAll()
    println(count)
}

Semaphore演示:

runBlocking {
    var count = 0
    val semaphore = Semaphore(1)
    List(1000) {
        GlobalScope.launch {
            semaphore.withPermit { count++ }
        }
    }.joinAll()
    println(count)
}
(3)避免访问外部可变状态

编写函数时要求它不得访问外部状态,只能基于参数做运算,通过返回值提供运算结果。

runBlocking {
    var count = 0
    var result = count + List(1000) {
        GlobalScope.async { 1 }
    }.map { it.await() }.sum()
    println(result)
}

[完...]

相关文章

网友评论

    本文标题:kotlin<第十二篇>:协程并发安全

    本文链接:https://www.haomeiwen.com/subject/merqldtx.html