diff --git a/docs/core/run-time-config/threading.md b/docs/core/run-time-config/threading.md index 2682524b80176..f2656ae764a8f 100644 --- a/docs/core/run-time-config/threading.md +++ b/docs/core/run-time-config/threading.md @@ -94,6 +94,40 @@ Project file: ``` +## Thread injection in response to blocking work items + +In some cases, the thread pool detects work items that block its threads. To compensate, it injects more threads. You can use the following [runtime configuration](https://github.com/dotnet/docs/blob/main/docs/core/run-time-config/index.md) settings to configure thread injection in response to blocking work items. Currently, these settings take effect only for work items that wait for another task to complete, such as in typical [sync-over-async](https://devblogs.microsoft.com/pfxteam/should-i-expose-synchronous-wrappers-for-asynchronous-methods/) cases. + +| *runtimeconfig.json* setting name | Description | +| - | - | +| `System.Threading.ThreadPool.Blocking.ThreadsToAddWithoutDelay_ProcCountFactor` | After the thread count based on `MinThreads` is reached, this value (after it is multiplied by the processor count) specifies how many additional threads may be created without a delay. | +| `System.Threading.ThreadPool.Blocking.ThreadsPerDelayStep_ProcCountFactor` | After the thread count based on `ThreadsToAddWithoutDelay` is reached, this value (after it is multiplied by the processor count) specifies after how many threads an additional `DelayStepMs` would be added to the delay before each new thread is created. | +| `System.Threading.ThreadPool.Blocking.DelayStepMs` | After the thread count based on `ThreadsToAddWithoutDelay` is reached, this value specifies how much additional delay to add per `ThreadsPerDelayStep` threads, which would be applied before each new thread is created. | +| `System.Threading.ThreadPool.Blocking.MaxDelayMs` | After the thread count based on `ThreadsToAddWithoutDelay` is reached, this value specifies the max delay to use before each new thread is created. | + +### How the configuration settings take effect + +- After the thread count based on `MinThreads` is reached, up to `ThreadsToAddWithoutDelay` additional threads may be created without a delay. +- After that, before each additional thread is created, a delay is induced, starting with `DelayStepMs`. +- For every `ThreadsPerDelayStep` threads that are added with a delay, an additional `DelayStepMs` is added to the delay. +- The delay may not exceed `MaxDelayMs`. +- Delays are only induced before creating threads. If threads are already available, they would be released without delay to compensate for blocking work items. +- Physical memory usage and limits are also used and, beyond a threshold, the system switches to slower thread injection. + +### Examples + +*runtimeconfig.json* file: + +```json +{ + "runtimeOptions": { + "configProperties": { + "System.Threading.ThreadPool.Blocking.ThreadsToAddWithoutDelay_ProcCountFactor": 5 + } + } +} +``` + ## `AutoreleasePool` for managed threads - Configures whether each managed thread receives an implicit [`NSAutoreleasePool`](https://developer.apple.com/documentation/foundation/nsautoreleasepool) when running on a supported macOS platform. diff --git a/docs/csharp/language-reference/keywords/volatile.md b/docs/csharp/language-reference/keywords/volatile.md index 63609220772b1..ee308e11decf7 100644 --- a/docs/csharp/language-reference/keywords/volatile.md +++ b/docs/csharp/language-reference/keywords/volatile.md @@ -11,10 +11,10 @@ ms.assetid: 78089bc7-7b38-4cfd-9e49-87ac036af009 --- # volatile (C# Reference) -The `volatile` keyword indicates that a field might be modified by multiple threads that are executing at the same time. The compiler, the runtime system, and even hardware may rearrange reads and writes to memory locations for performance reasons. Fields that are declared `volatile` are not subject to these optimizations. Adding the `volatile` modifier ensures that all threads will observe volatile writes performed by any other thread in the order in which they were performed. There is no guarantee of a single total ordering of volatile writes as seen from all threads of execution. +The `volatile` keyword indicates that a field might be modified by multiple threads that are executing at the same time. The compiler, the runtime system, and even hardware may rearrange reads and writes to memory locations for performance reasons. Fields that are declared `volatile` are excluded from certain kinds of optimizations. There is no guarantee of a single total ordering of volatile writes as seen from all threads of execution. For more information, see the class. > [!NOTE] -> When writing to a field marked `volatile`, the `volatile` keyword controls the order in which writes are performed. It does not guarantee that these writes are immediately visible to other threads. +> On a multiprocessor system, a volatile read operation does not guarantee to obtain the latest value written to that memory location by any processor. Similarly, a volatile write operation does not guarantee that the value written would be immediately visible to other processors. The `volatile` keyword can be applied to fields of these types: diff --git a/docs/framework/performance/lazy-initialization.md b/docs/framework/performance/lazy-initialization.md index 51ad07b299207..30951b1e54ac5 100644 --- a/docs/framework/performance/lazy-initialization.md +++ b/docs/framework/performance/lazy-initialization.md @@ -79,6 +79,8 @@ ms.assetid: 56b4ae5c-4745-44ff-ad78-ffe4fcde6b9b As the table shows, specifying for the `mode` parameter is the same as specifying `true` for the `isThreadSafe` parameter, and specifying is the same as specifying `false`. + For more information about what `Execution` and `Publication` refer to, see . + Specifying allows multiple threads to attempt to initialize the instance. Only one thread can win this race, and all the other threads receive the value that was initialized by the successful thread. If an exception is thrown on a thread during initialization, that thread does not receive the value set by the successful thread. Exceptions are not cached, so a subsequent attempt to access the property can result in successful initialization. This differs from the way exceptions are treated in other modes, which is described in the following section. For more information, see the enumeration.