From ff4a52a752606e07af4c69085af60933747ee6dc Mon Sep 17 00:00:00 2001 From: "Andy De George (from Dev Box)" Date: Fri, 3 Jul 2026 12:48:32 -0700 Subject: [PATCH 1/4] Add notes and references to threading.lock --- docs/standard/threading/managed-threading-basics.md | 3 +++ .../threading/managed-threading-best-practices.md | 3 ++- .../threading/overview-of-synchronization-primitives.md | 8 +++++++- .../threading/synchronizing-data-for-multithreading.md | 6 +++++- docs/standard/threading/threading-objects-and-features.md | 3 +++ 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/docs/standard/threading/managed-threading-basics.md b/docs/standard/threading/managed-threading-basics.md index ad86252376267..85fdd2b09c037 100644 --- a/docs/standard/threading/managed-threading-basics.md +++ b/docs/standard/threading/managed-threading-basics.md @@ -13,6 +13,9 @@ ms.assetid: b2944911-0e8f-427d-a8bb-077550618935 The first five articles of this section are designed to help you determine when to use managed threading and to explain some basic features. For information on classes that provide additional features, see [Threading Objects and Features](threading-objects-and-features.md) and [Overview of Synchronization Primitives](overview-of-synchronization-primitives.md). +> [!NOTE] +> In .NET 9 and C# 13 or later, use a dedicated instance with the C# [lock statement](../../csharp/language-reference/statements/lock.md). This approach improves performance and reduces mistakes from locking the wrong object. In Visual Basic, continue to use [SyncLock](../../visual-basic/language-reference/statements/synclock-statement.md). + The remaining articles in this section cover advanced topics, including the interaction of managed threading with the Windows operating system. > [!NOTE] diff --git a/docs/standard/threading/managed-threading-best-practices.md b/docs/standard/threading/managed-threading-best-practices.md index dd9c3feb14d65..8af46be364db2 100644 --- a/docs/standard/threading/managed-threading-best-practices.md +++ b/docs/standard/threading/managed-threading-best-practices.md @@ -2,7 +2,6 @@ title: "Managed Threading Best Practices" description: Learn managed threading best practices in .NET. Work with difficult situations such as coordinating many threads or handling blocking threads. ms.date: 03/13/2026 -ai-usage: ai-assisted dev_langs: - "csharp" - "vb" @@ -95,6 +94,8 @@ Consider the following guidelines when using multiple threads: - Use caution when locking on instances, for example `lock(this)` in C# or `SyncLock(Me)` in Visual Basic. If other code in your application, external to the type, takes a lock on the object, deadlocks could occur. +- In .NET 9 and C# 13 or later, use a dedicated instance as your lock object with the C# [lock statement](../../csharp/language-reference/statements/lock.md). In Visual Basic, continue to use a dedicated private reference type instance with `SyncLock`. + - Do ensure that a thread that has entered a monitor always leaves that monitor, even if an exception occurs while the thread is in the monitor. The C# [lock](../../csharp/language-reference/statements/lock.md) statement and the Visual Basic [SyncLock](../../visual-basic/language-reference/statements/synclock-statement.md) statement provide this behavior automatically, employing a **finally** block to ensure that is called. If you cannot ensure that **Exit** will be called, consider changing your design to use **Mutex**. A mutex is automatically released when the thread that currently owns it terminates. - Do use multiple threads for tasks that require different resources, and avoid assigning multiple threads to a single resource. For example, any task involving I/O benefits from having its own thread, because that thread will block during I/O operations and thus allow other threads to execute. User input is another resource that benefits from a dedicated thread. On a single-processor computer, a task that involves intensive computation coexists with user input and with tasks that involve I/O, but multiple computation-intensive tasks contend with each other. diff --git a/docs/standard/threading/overview-of-synchronization-primitives.md b/docs/standard/threading/overview-of-synchronization-primitives.md index e794a77dc412d..f68cd9f132efa 100644 --- a/docs/standard/threading/overview-of-synchronization-primitives.md +++ b/docs/standard/threading/overview-of-synchronization-primitives.md @@ -52,7 +52,13 @@ You can coordinate the interaction of threads that acquire a lock on the same ob For more information, see the API reference. > [!NOTE] -> Use the [lock](../../csharp/language-reference/statements/lock.md) statement in C# and the [SyncLock](../../visual-basic/language-reference/statements/synclock-statement.md) statement in Visual Basic to synchronize access to a shared resource instead of using the class directly. Those statements are implemented by using the and methods and a `try…finally` block to ensure that the acquired lock is always released. +> Use the [lock](../../csharp/language-reference/statements/lock.md) statement in C# and the [SyncLock](../../visual-basic/language-reference/statements/synclock-statement.md) statement in Visual Basic to synchronize access to a shared resource instead of using the class directly. +> +> In .NET 9 and C# 13 or later, use a dedicated instance for best performance. In that case, `lock` uses . +> +> This approach is better than locking a general `object` because it uses a lock type designed for synchronization and reduces accidental reuse of unrelated objects. +> +> Visual Basic doesn't support `System.Threading.Lock` in `SyncLock`, so use a dedicated private reference type for `SyncLock`. For C# versions before 13, for .NET versions before 9, and for Visual Basic, these statements use and with a `try…finally` block to ensure that the acquired lock is always released. ### Mutex class diff --git a/docs/standard/threading/synchronizing-data-for-multithreading.md b/docs/standard/threading/synchronizing-data-for-multithreading.md index 50ffff985257c..c52202c34143d 100644 --- a/docs/standard/threading/synchronizing-data-for-multithreading.md +++ b/docs/standard/threading/synchronizing-data-for-multithreading.md @@ -46,7 +46,11 @@ When multiple threads can make calls to the properties and methods of a single o Both Visual Basic and C# support the marking of blocks of code with a particular language keyword, the `lock` statement in C# or the `SyncLock` statement in Visual Basic. When the code is executed by a thread, an attempt is made to acquire the lock. If the lock has already been acquired by another thread, the thread blocks until the lock becomes available. When the thread exits the synchronized block of code, the lock is released, no matter how the thread exits the block. > [!NOTE] -> Beginning in C# 13, the `lock` statement recognizes if the locked object is an instance of and uses the `EnterScope` method to create a synchronized region. The `lock`, when the target isn't a `Lock` instance, and `SyncLock` statements are implemented using and , so other methods of can be used in conjunction with them within the synchronized region. +> In .NET 9 and C# 13 or later, if the `lock` target is a dedicated instance, the `lock` statement uses to create a synchronized region. +> +> Visual Basic doesn't support `System.Threading.Lock` in `SyncLock`, so continue to use `SyncLock` with a dedicated private reference type. +> +> If the `lock` target isn't a `Lock` instance, and for all `SyncLock` usage, the compiler uses and . Because of that implementation, you can still use other methods in the synchronized region. You can also decorate a method with a with a value of , which has the same effect as using or one of the compiler keywords to lock the entire body of the method. diff --git a/docs/standard/threading/threading-objects-and-features.md b/docs/standard/threading/threading-objects-and-features.md index 980d2d7ad47b0..7ab1f0a0fcdc7 100644 --- a/docs/standard/threading/threading-objects-and-features.md +++ b/docs/standard/threading/threading-objects-and-features.md @@ -24,6 +24,9 @@ Along with the class |[SpinLock](spinlock.md)|Describes the structure, which is a lightweight alternative to the class for certain low-level locking scenarios.| |[SpinWait](spinwait.md)|Describes the structure, which provides support for spin-based waiting.| +> [!NOTE] +> In .NET 9 and C# 13 or later, prefer a dedicated instance with the C# `lock` statement for general locking scenarios. This approach improves performance and reduces mistakes from locking shared objects that weren't meant for synchronization. For details, see [Overview of synchronization primitives](overview-of-synchronization-primitives.md) and [The lock statement](../../csharp/language-reference/statements/lock.md). In Visual Basic, continue to use `SyncLock`. + ## See also - From 0e2cf48e7852053a2e15a3d13976a55f69803fe6 Mon Sep 17 00:00:00 2001 From: "Andy (Steve) De George" <67293991+adegeo@users.noreply.github.com> Date: Mon, 6 Jul 2026 12:07:35 -0700 Subject: [PATCH 2/4] Update docs/standard/threading/overview-of-synchronization-primitives.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- .../threading/overview-of-synchronization-primitives.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/standard/threading/overview-of-synchronization-primitives.md b/docs/standard/threading/overview-of-synchronization-primitives.md index f68cd9f132efa..913909246a9a9 100644 --- a/docs/standard/threading/overview-of-synchronization-primitives.md +++ b/docs/standard/threading/overview-of-synchronization-primitives.md @@ -52,7 +52,7 @@ You can coordinate the interaction of threads that acquire a lock on the same ob For more information, see the API reference. > [!NOTE] -> Use the [lock](../../csharp/language-reference/statements/lock.md) statement in C# and the [SyncLock](../../visual-basic/language-reference/statements/synclock-statement.md) statement in Visual Basic to synchronize access to a shared resource instead of using the class directly. +> To synchronize access to a shared resource, use the [lock](../../csharp/language-reference/statements/lock.md) statement in C# and the [SyncLock](../../visual-basic/language-reference/statements/synclock-statement.md) statement in Visual Basic instead of using the class directly. > > In .NET 9 and C# 13 or later, use a dedicated instance for best performance. In that case, `lock` uses . > From 22b64f3407b891781e041d57c9312ec4981ed245 Mon Sep 17 00:00:00 2001 From: "Andy (Steve) De George" <67293991+adegeo@users.noreply.github.com> Date: Mon, 6 Jul 2026 12:07:57 -0700 Subject: [PATCH 3/4] Update docs/standard/threading/overview-of-synchronization-primitives.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- .../threading/overview-of-synchronization-primitives.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/standard/threading/overview-of-synchronization-primitives.md b/docs/standard/threading/overview-of-synchronization-primitives.md index 913909246a9a9..2637ca1681b88 100644 --- a/docs/standard/threading/overview-of-synchronization-primitives.md +++ b/docs/standard/threading/overview-of-synchronization-primitives.md @@ -58,7 +58,7 @@ For more information, see the API reference. > > This approach is better than locking a general `object` because it uses a lock type designed for synchronization and reduces accidental reuse of unrelated objects. > -> Visual Basic doesn't support `System.Threading.Lock` in `SyncLock`, so use a dedicated private reference type for `SyncLock`. For C# versions before 13, for .NET versions before 9, and for Visual Basic, these statements use and with a `try…finally` block to ensure that the acquired lock is always released. +> Visual Basic doesn't support `System.Threading.Lock` in `SyncLock`, so use a dedicated private reference type for `SyncLock`. For C# versions before 13, .NET versions before 9, and Visual Basic, these statements use and with a `try…finally` block to ensure that the acquired lock is always released. ### Mutex class From e520ca2b3ef8e4d310d875a928d14d374956bd19 Mon Sep 17 00:00:00 2001 From: "Andy (Steve) De George" <67293991+adegeo@users.noreply.github.com> Date: Mon, 6 Jul 2026 12:10:45 -0700 Subject: [PATCH 4/4] Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- docs/standard/threading/managed-threading-basics.md | 3 +-- docs/standard/threading/threading-objects-and-features.md | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/standard/threading/managed-threading-basics.md b/docs/standard/threading/managed-threading-basics.md index 85fdd2b09c037..6705bc8a9136e 100644 --- a/docs/standard/threading/managed-threading-basics.md +++ b/docs/standard/threading/managed-threading-basics.md @@ -13,8 +13,7 @@ ms.assetid: b2944911-0e8f-427d-a8bb-077550618935 The first five articles of this section are designed to help you determine when to use managed threading and to explain some basic features. For information on classes that provide additional features, see [Threading Objects and Features](threading-objects-and-features.md) and [Overview of Synchronization Primitives](overview-of-synchronization-primitives.md). -> [!NOTE] -> In .NET 9 and C# 13 or later, use a dedicated instance with the C# [lock statement](../../csharp/language-reference/statements/lock.md). This approach improves performance and reduces mistakes from locking the wrong object. In Visual Basic, continue to use [SyncLock](../../visual-basic/language-reference/statements/synclock-statement.md). +> In .NET 9 and C# 13 or later, use a dedicated instance with the C# [lock statement](../../csharp/language-reference/statements/lock.md). This approach improves performance and reduces mistakes from locking the wrong object. In Visual Basic, continue to use [SyncLock](../../visual-basic/language-reference/statements/synclock-statement.md) with a dedicated private reference type. The remaining articles in this section cover advanced topics, including the interaction of managed threading with the Windows operating system. diff --git a/docs/standard/threading/threading-objects-and-features.md b/docs/standard/threading/threading-objects-and-features.md index 7ab1f0a0fcdc7..63165df15e846 100644 --- a/docs/standard/threading/threading-objects-and-features.md +++ b/docs/standard/threading/threading-objects-and-features.md @@ -25,7 +25,7 @@ Along with the class |[SpinWait](spinwait.md)|Describes the structure, which provides support for spin-based waiting.| > [!NOTE] -> In .NET 9 and C# 13 or later, prefer a dedicated instance with the C# `lock` statement for general locking scenarios. This approach improves performance and reduces mistakes from locking shared objects that weren't meant for synchronization. For details, see [Overview of synchronization primitives](overview-of-synchronization-primitives.md) and [The lock statement](../../csharp/language-reference/statements/lock.md). In Visual Basic, continue to use `SyncLock`. +> In .NET 9 and C# 13 or later, prefer a dedicated instance with the C# `lock` statement for general locking scenarios. This approach improves performance and reduces mistakes from locking shared objects that weren't meant for synchronization. For details, see [Overview of synchronization primitives](overview-of-synchronization-primitives.md) and [The lock statement](../../csharp/language-reference/statements/lock.md). In Visual Basic, continue to use `SyncLock` with a dedicated private reference type. ## See also