Note on systems with nCPUs <= 2
diff --git a/coroutines-guide.md b/coroutines-guide.md
index 469a335..954ae6b 100644
--- a/coroutines-guide.md
+++ b/coroutines-guide.md
@@ -1,4 +1,4 @@
-<!--- INCLUDE .*/example-([a-z]+)-([0-9]+)\.kt
+<!--- INCLUDE .*/example-([a-z]+)-([0-9a-z]+)\.kt
/*
* Copyright 2016-2017 JetBrains s.r.o.
*
@@ -1549,7 +1549,7 @@
Let us launch a thousand coroutines all doing the same action thousand times (for a total of a million executions).
We'll also measure their completion time for further comparisons:
-<!--- INCLUDE .*/example-sync-([0-9]+).kt
+<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt
import kotlin.coroutines.experimental.CoroutineContext
import kotlin.system.measureTimeMillis
-->
@@ -1582,7 +1582,7 @@
}
```
-<!--- INCLUDE .*/example-sync-([0-9]+).kt -->
+<!--- INCLUDE .*/example-sync-([0-9a-z]+).kt -->
We start with a very simple action that increments a shared mutable variable using
multi-threaded [CommonPool] context.
@@ -1608,6 +1608,29 @@
What does it print at the end? It is highly unlikely to ever print "Counter = 1000000", because a thousand coroutines
increment the `counter` concurrently from multiple threads without any synchronization.
+> Note: if you have an old system with 2 or fewer CPUs, then you _will_ consistently see 1000000, because
+`CommonPool` is running in only one thread in this case. To reproduce the problem you'll need to make the
+following change:
+
+```kotlin
+val mtContext = newFixedThreadPoolContext(2, "mtPool") // explicitly define context with two threads
+var counter = 0
+
+fun main(args: Array<String>) = runBlocking<Unit> {
+ massiveRun(mtContext) { // use it instead of CommonPool in this sample and below
+ counter++
+ }
+ println("Counter = $counter")
+}
+```
+
+> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01b.kt)
+
+<!--- TEST LINES_START
+Completed 1000000 actions in
+Counter =
+-->
+
### Volatiles are of no help
There is common misconception that making a variable `volatile` solves concurrency problem. Let us try it:
diff --git a/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01b.kt b/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01b.kt
new file mode 100644
index 0000000..68b320d
--- /dev/null
+++ b/kotlinx-coroutines-core/src/test/kotlin/guide/example-sync-01b.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
+package guide.sync.example01b
+
+import kotlinx.coroutines.experimental.*
+import kotlin.coroutines.experimental.CoroutineContext
+import kotlin.system.measureTimeMillis
+
+suspend fun massiveRun(context: CoroutineContext, action: suspend () -> Unit) {
+ val n = 1000 // number of coroutines to launch
+ val k = 1000 // times an action is repeated by each coroutine
+ val time = measureTimeMillis {
+ val jobs = List(n) {
+ launch(context) {
+ repeat(k) { action() }
+ }
+ }
+ jobs.forEach { it.join() }
+ }
+ println("Completed ${n * k} actions in $time ms")
+}
+
+val mtContext = newFixedThreadPoolContext(2, "mtPool") // explicitly define context with two threads
+var counter = 0
+
+fun main(args: Array<String>) = runBlocking<Unit> {
+ massiveRun(mtContext) { // use it instead of CommonPool in this sample and below
+ counter++
+ }
+ println("Counter = $counter")
+}
diff --git a/kotlinx-coroutines-core/src/test/kotlin/guide/test/GuideTest.kt b/kotlinx-coroutines-core/src/test/kotlin/guide/test/GuideTest.kt
index ee95ad2..9655454 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/guide/test/GuideTest.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/guide/test/GuideTest.kt
@@ -354,6 +354,14 @@
}
@Test
+ fun testGuideSyncExample01b() {
+ test { guide.sync.example01b.main(emptyArray()) }.verifyLinesStart(
+ "Completed 1000000 actions in",
+ "Counter ="
+ )
+ }
+
+ @Test
fun testGuideSyncExample02() {
test { guide.sync.example02.main(emptyArray()) }.verifyLinesStart(
"Completed 1000000 actions in",