Skip to content

Commit 086d52a

Browse files
authored
Explain that limitedParallelism(1) is not a mutex (#4434)
1 parent e5bb191 commit 086d52a

File tree

1 file changed

+38
-1
lines changed

1 file changed

+38
-1
lines changed

kotlinx-coroutines-core/common/src/CoroutineDispatcher.kt

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ public abstract class CoroutineDispatcher :
134134
*
135135
* One of the common patterns is confining the execution of specific tasks to a sequential execution in background
136136
* with `limitedParallelism(1)` invocation.
137-
* For that purpose, the implementation guarantees that tasks are executed sequentially and that a happens-before relation
137+
* For that purpose, the implementation guarantees that sections of code between suspensions
138+
* are executed sequentially and that a happens-before relation
138139
* is established between them:
139140
*
140141
* ```
@@ -149,6 +150,42 @@ public abstract class CoroutineDispatcher :
149150
* ```
150151
* Note that there is no guarantee that the underlying system thread will always be the same.
151152
*
153+
* #### It is not a mutex!
154+
*
155+
* **Pitfall**: [limitedParallelism] limits how many threads can execute some code in parallel,
156+
* but does not limit how many coroutines execute concurrently!
157+
*
158+
* For example:
159+
*
160+
* ```
161+
* val notAMutex = Dispatchers.Default.limitedParallelism(1)
162+
*
163+
* repeat(3) {
164+
* launch(notAMutex) {
165+
* println("Coroutine $it entering...")
166+
* delay(20.milliseconds)
167+
* println("Coroutine $it leaving.")
168+
* }
169+
* }
170+
* ```
171+
*
172+
* The output will be similar to this:
173+
*
174+
* ```
175+
* Coroutine 0 entering...
176+
* Coroutine 1 entering...
177+
* Coroutine 2 entering...
178+
* Coroutine 0 leaving.
179+
* Coroutine 1 leaving.
180+
* Coroutine 2 leaving.
181+
* ```
182+
*
183+
* This means that coroutines are not guaranteed to run to completion before the dispatcher starts executing
184+
* code from another coroutine.
185+
* The only guarantee in this example is that two `println` calls will not occur in several threads simultaneously.
186+
*
187+
* Use a [kotlinx.coroutines.sync.Mutex] or a [kotlinx.coroutines.sync.Semaphore] for limiting concurrency.
188+
*
152189
* ### Dispatchers.IO
153190
*
154191
* `Dispatcher.IO` is considered _elastic_ for the purposes of limited parallelism -- the sum of

0 commit comments

Comments
 (0)