Skip to content

Instantly share code, notes, and snippets.

@chimerast
Created September 4, 2020 17:45
Show Gist options
  • Save chimerast/6a1941a7d9b4387f661a03b7478db2f7 to your computer and use it in GitHub Desktop.
Save chimerast/6a1941a7d9b4387f661a03b7478db2f7 to your computer and use it in GitHub Desktop.
Coroutineの説明用に作って見た
package example
import kotlinx.coroutines.*
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
fun main() {
val nCount = 100000
useCoroutine(1) { unsafe(this, nCount) }.also { println() }
useCoroutine(10) { unsafe(this, nCount) }.also { println() }
useCoroutine(1) { maybeUnsafe(this, nCount) }.also { println() }
useCoroutine(10) { maybeUnsafe(this, nCount) }.also { println() }
useCoroutine(1) { safe(this, nCount) }.also { println() }
useCoroutine(10) { safe(this, nCount) }.also { println() }
ThreadName.printActives()
}
fun useCoroutine(nThreads: Int, block: suspend CoroutineScope.() -> Unit) {
val pool = Executors.newFixedThreadPool(nThreads)
pool.asCoroutineDispatcher().use {
runBlocking(it) {
block()
}
}
pool.awaitTermination(10, TimeUnit.MINUTES)
}
suspend fun unsafe(scope: CoroutineScope, nCount: Int) {
ThreadName.printCurrent()
var counter = 0
List(nCount) {
scope.async {
counter++
}
}.awaitAll()
println("total counter: $counter")
}
suspend fun maybeUnsafe(scope: CoroutineScope, nCount: Int) {
ThreadName.printCurrent()
val lock = Object()
var counter = 0
List(nCount) {
scope.async {
// lockというインスタンスで、critical sectionを作り上げているが、
// スレッド間でCPUレジスタレベルでデータの同期が取れているのは、lockとその内包するattributeだけで、
// counterは実はデータ同期の対象外、まあ、これくらいなら動くけど、いつ死ぬかはわからない
synchronized(lock) {
counter++
}
}
}.awaitAll()
println("total counter: $counter")
}
suspend fun safe(scope: CoroutineScope, nCount: Int) {
ThreadName.printCurrent()
val counter = AtomicInteger(0)
List(nCount) {
scope.async {
counter.getAndIncrement()
}
}.awaitAll()
println("total counter: $counter")
}
object ThreadName {
fun printCurrent() {
println(Thread.currentThread().name)
}
fun printActives() {
val threads = arrayOfNulls<Thread>(Thread.activeCount())
Thread.enumerate(threads)
threads.mapNotNull { it?.name }.forEach { println(it) }
}
}
@chimerast
Copy link
Author

一旦挙動のチェックとして。一部作って見た。サチったときの挙動をどう再現するかが難しい。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment