@@ -24,15 +24,20 @@ and it does not change during the non-suspending execution within the same threa
24
24
25
25
If ` runBlocking ` happens to be invoked on a thread from ` CoroutineDispatcher ` , it may cause a thread starvation problem
26
26
(Kotlin #3983 ). This happens because ` runBlocking ` does not release an associated computational permit while it parks the
27
- thread. To fix this, a parallelism compensation mechanism is introduced. When ` runBlocking ` decides to park a
28
- ` CoroutineDispatcher ` thread, it first increases the allowed parallelism limit of the ` CoroutineDispatcher ` . After
29
- the thread unparks, ` runBlocking ` notifies the dispatcher that the parallelism limit should be lowered back. It is
30
- important that the effective parallelism may temporarily exceed the current allowed parallelism limit. The
31
- ` CoroutineDispatcher ` 's worker take care of adjusting the effective parallelism if it needs to be decreased.
27
+ thread. To fix this, a parallelism compensation mechanism is introduced. Some ` CoroutineDispatcher ` s (such as
28
+ ` Dispatchers.Default ` , ` Dispatchers.IO ` and others) support ` ParallelismCompensation ` , meaning that these dispatchers
29
+ can be notified that they should increase parallelism and parallelism limit, or they should decrease it. It is important that these
30
+ are only requests and dispatchers are in full control on how and when they need to adjust the effective parallelism.
31
+ It also means that the instantaneous parallelism may exceed the current allowed parallelism limit for the given dispatcher.
32
+
33
+ ` runBlockingWithParallelismCompensation ` (further abbreviated as ` rBWPC ` ) is introduced as a counterpart of ` runBlocking `
34
+ with the following behavioral change. When ` rBWPC ` decides to park a ` CoroutineDispatcher ` thread, it first increases the allowed parallelism
35
+ limit of the ` CoroutineDispatcher ` . After the thread unparks, ` rBWPC ` notifies the dispatcher that the parallelism limit should be lowered back.
36
+ A separate function is introduced because parallelism compensation is now always a desirable behavior.
32
37
33
38
It is easy to see that this behavior cannot be general for ` CoroutineDispatcher ` s, at least because it breaks the contract
34
39
of ` LimitedDispatcher ` (one that can be acquired via ` .limitedParallelism ` ). It means that parallelism compensation
35
- cannot work for ` LimitedDispatcher ` , so ` runBlocking ` can still cause starvation issues there, but it seems rather
40
+ cannot work for ` LimitedDispatcher ` , so ` runBlockingWithParallelismCompensation ` can still cause starvation issues there, but it seems rather
36
41
expected.
37
42
38
43
Parallelism compensation support is internal and is implemented for ` Dispatchers.Default ` and ` Dispatchers.IO ` .
@@ -42,5 +47,7 @@ with `.softLimitedParallelism`, e.g., `.limitedParallelism(1)` may be used as a
42
47
exceeding the parallelism limit would eliminate this (likely expected) side effect.
43
48
44
49
### API
50
+ - ` runBlockingWithParallelismCompensation ` - an analogue of ` runBlocking ` which also compensates parallelism of the
51
+ associated coroutine dispatcher when it decides to park the thread
45
52
- ` CoroutineDispatcher.softLimitedParallelism ` – an analogue of ` .limitedParallelism ` which supports
46
53
parallelism compensation
0 commit comments