class CoroutineText03 {
@Test
fun `test not safe concurrent`() = runBlocking<Unit> {
var count = 0
List(1000) {
GlobalScope.launch { count++ }
}.joinAll()
println(count)
}
}
结果不是固定的。。
因为 他们不是原子性的操作。在a+1=b的时候 没有进行b+1 而是又跑了一遍a+1
就没有计算到结果当中
可以使用
@Test
fun `test safe concurrent`() = runBlocking<Unit> {
var count = AtomicInteger(0)
List(1000) {
GlobalScope.launch { count.incrementAndGet() }
}.joinAll()
println(count)
}
来保证其源自顺序
AtomicInteger 是来自java的东西。
协程也提供了并发安全
1、Channel
2、Mutex 轻量级锁
他的lock和unlock从语义上与线程锁比较类似,之所以轻量,是因为它在获取不到锁时不会阻塞县城。而是挂起等待锁的释放
@Test
fun `test safe concurrent tools`() = runBlocking<Unit> {
var count = 0
val mutex = Mutex()
List(1000) {
GlobalScope.launch {
mutex.withLock {
count++
}
}
}.joinAll()
println(count)
}
3 Semaphore:轻量级信号量,信号量可以有多个,协程在获取到信号量后即可执行并发操作
@Test
fun `test safe concurrent tools2`() = runBlocking<Unit> {
var count = 0
val semaphore = Semaphore(1)
List(1000) {
GlobalScope.launch {
semaphore.withPermit {
count++
}
}
}.joinAll()
println(count)
}
安全的都是返回1000不再打印
还有一种。。在外面加 不过这种应该是效率没有很高。
@Test
fun `test avoid access outer variable`() = runBlocking<Unit> {
val count = 0
val result = count + List(1000) {
GlobalScope.async { 1 }
}.map { it.await() }.sum()
println(result)
}