当前位置: 首页>后端>正文

kotlin 协程并发安全

(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)
}

作者:NoBugException
链接:https://www.jianshu.com/p/457e80cd73d5
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


https://www.xamrdz.com/backend/3tj1929438.html

相关文章: