kotlin<第十二篇>:協(xié)程并發(fā)安全

(1)不安全的并發(fā)訪問

我們使用線程在解決并發(fā)問題的時候總是會遇到線程安全的問題,而Java平臺上的Kotlin協(xié)程實現(xiàn)免不了存在并發(fā)調(diào)度的情況,因此線程安全同樣值得留意。

runBlocking {

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

}

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

(2)協(xié)程并發(fā)安全

在Java中,提供了原子性的對象:AtomicInteger,可以保證協(xié)程的安全性:

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

除了我們在線程中常用的解決并發(fā)問題的手段之外,協(xié)程框架也提供了一些并發(fā)安全工具,包括:

  • Channel:并發(fā)安全的消息通道;
  • Mutex:輕量級鎖,它的lock和unlock從語義上與線程鎖比較類似,之所以輕量級是因為它在獲取不到鎖時不會阻塞線程,二十掛起等待鎖的釋放。
  • Semaphore:輕量級信號量,信號量可以有多個,協(xié)程在獲取到信號量后即可執(zhí)行并發(fā)操作。當(dāng)Semaphore的參數(shù)為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)避免訪問外部可變狀態(tài)

編寫函數(shù)時要求它不得訪問外部狀態(tài),只能基于參數(shù)做運算,通過返回值提供運算結(jié)果。

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

[完...]

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容