Skip to content

Commit 1d3790d

Browse files
CopilotBillWagner
andauthored
Add warnings and guidance against using volatile keyword (#47282)
* Initial plan * Add warnings and guidance against using volatile keyword Co-authored-by: BillWagner <[email protected]> * Remove "stronger guarantees" statement as requested in review Co-authored-by: BillWagner <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: BillWagner <[email protected]>
1 parent 38ac9aa commit 1d3790d

File tree

1 file changed

+19
-0
lines changed

1 file changed

+19
-0
lines changed

docs/csharp/language-reference/keywords/volatile.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ ms.assetid: 78089bc7-7b38-4cfd-9e49-87ac036af009
1313

1414
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 <xref:System.Threading.Volatile> class.
1515

16+
> [!CAUTION]
17+
> The `volatile` keyword is often misunderstood and misused in multithreaded programming. In most scenarios, you should use safer and more reliable alternatives instead of `volatile`. Modern .NET provides better concurrency tools like the <xref:System.Threading.Interlocked> class, the [`lock`](../statements/lock.md) statement, or higher-level synchronization primitives. These alternatives provide clearer semantics and stronger guarantees than `volatile`. Consider using `volatile` only in rare, advanced scenarios where you fully understand its limitations and have verified it's the appropriate solution.
18+
1619
> [!NOTE]
1720
> 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.
1821
@@ -27,8 +30,21 @@ The `volatile` keyword can be applied to fields of these types:
2730

2831
Other types, including `double` and `long`, cannot be marked `volatile` because reads and writes to fields of those types cannot be guaranteed to be atomic. To protect multi-threaded access to those types of fields, use the <xref:System.Threading.Interlocked> class members or protect access using the [`lock`](../statements/lock.md) statement.
2932

33+
For most multithreaded scenarios, even with supported types, prefer using <xref:System.Threading.Interlocked> operations, [`lock`](../statements/lock.md) statements, or other synchronization primitives instead of `volatile`. These alternatives are less prone to subtle concurrency bugs.
34+
3035
The `volatile` keyword can only be applied to fields of a `class` or `struct`. Local variables cannot be declared `volatile`.
3136

37+
## Alternatives to volatile
38+
39+
In most cases, you should use one of these safer alternatives instead of `volatile`:
40+
41+
- **<xref:System.Threading.Interlocked> operations**: Provide atomic operations for numeric types and reference assignments. These are generally faster and provide stronger guarantees than `volatile`.
42+
- **[`lock` statement](../statements/lock.md)**: Provides mutual exclusion and memory barriers. Use for protecting larger critical sections.
43+
- **<xref:System.Threading.Volatile> class**: Provides explicit volatile read and write operations with clearer semantics than the `volatile` keyword.
44+
- **Higher-level synchronization primitives**: Such as <xref:System.Threading.ReaderWriterLockSlim>, <xref:System.Threading.Semaphore>, or concurrent collections from <xref:System.Collections.Concurrent>.
45+
46+
The `volatile` keyword doesn't provide atomicity for operations other than assignment, doesn't prevent race conditions, and doesn't provide ordering guarantees for other memory operations. These limitations make it unsuitable for most concurrency scenarios.
47+
3248
## Example
3349

3450
The following example shows how to declare a public field variable as `volatile`.
@@ -52,3 +68,6 @@ With the `volatile` modifier added to the declaration of `_shouldStop` in place,
5268
- [Modifiers](index.md)
5369
- [lock statement](../statements/lock.md)
5470
- <xref:System.Threading.Interlocked>
71+
- <xref:System.Threading.Volatile>
72+
- <xref:System.Collections.Concurrent>
73+
- [Managed Threading](../../../standard/threading/managed-threading-basics.md)

0 commit comments

Comments
 (0)