同步基元概述Overview of synchronization primitives

.NET 提供了一系列可用于同步对共享资源或协调线程交互的访问的类型。.NET provides a range of types that you can use to synchronize access to a shared resource or coordinate thread interaction.

重要

使用相同的同步基元实例保护对共享资源的访问。Use the same synchronization primitive instance to protect access of a shared resource. 如果使用不同的同步基元实例保护同一资源,则将避开同步基元提供的保护。If you use different synchronization primitive instances to protect the same resource, you'll circumvent the protection provided by a synchronization primitive.

WaitHandle 类和轻量同步类型WaitHandle class and lightweight synchronization types

多个 .NET 同步基元派生自 System.Threading.WaitHandle 类,该类会封装本机操作系统同步句柄并将信号机制用于线程交互。Multiple .NET synchronization primitives derive from the System.Threading.WaitHandle class, which encapsulates a native operating system synchronization handle and uses a signaling mechanism for thread interaction. 这些类包括:Those classes include:

在 .NET Framework 中,由于 WaitHandle 派生自 System.MarshalByRefObject,因此,这些类型可用于跨应用程序域边界同步线程的活动。In the .NET Framework, because WaitHandle derives from System.MarshalByRefObject, these types can be used to synchronize the activities of threads across application domain boundaries.

在 .NET Framework 和 .NET Core 中,其中的一些类型可以表示已命名的系统同步句柄,这些句柄在整个操作系统中都可见并可用于进程间同步:In the .NET Framework and .NET Core, some of these types can represent named system synchronization handles, which are visible throughout the operating system and can be used for the inter-process synchronization:

  • Mutex(.NET Framework 和 .NET Core)、Mutex (.NET Framework and .NET Core),
  • Semaphore(.NET Framework 和 Windows 上的 .NET Core)、Semaphore (.NET Framework and .NET Core on Windows),
  • EventWaitHandle(.NET Framework 和 Windows 上的 .NET Core)。EventWaitHandle (.NET Framework and .NET Core on Windows).

有关详细信息,请参阅 WaitHandle API 参考。For more information, see the WaitHandle API reference.

轻量同步类型不依赖于基础操作系统句柄,通常会提供更好的性能。Lightweight synchronization types don't rely on underlying operating system handles and typically provide better performance. 但是,它们不能用于进程间同步。However, they cannot be used for the inter-process synchronization. 将这些类型用于一个应用程序中的线程同步。Use those types for thread synchronization within one application.

其中的一些类型是派生自 WaitHandle 的类型的替代项。Some of those types are alternatives to the types derived from WaitHandle. 例如,SemaphoreSlimSemaphore 的轻量替代项。For example, SemaphoreSlim is a lightweight alternative to Semaphore.

同步对共享资源的访问Synchronization of access to a shared resource

.NET 提供了一系列用于控制多个线程对共享资源的访问的同步基元。.NET provides a range of synchronization primitives to control access to a shared resource by multiple threads.

Monitor 类Monitor class

System.Threading.Monitor 类通过获取或释放用于标识资源的对象上的 lock 来授予对共享资源的相互独占访问权限。The System.Threading.Monitor class grants mutually exclusive access to a shared resource by acquiring or releasing a lock on the object that identifies the resource. 持有 lock 时,持有 lock 的线程可以再次获取并释放 lock。While a lock is held, the thread that holds the lock can again acquire and release the lock. 阻止任何其他线程获取 lock,Monitor.Enter 方法等待释放 lock。Any other thread is blocked from acquiring the lock and the Monitor.Enter method waits until the lock is released. Enter 方法可获取释放的 lock。The Enter method acquires a released lock. 还可以使用 Monitor.TryEnter 方法指定线程尝试获取 lock 的持续时间。You can also use the Monitor.TryEnter method to specify the amount of time during which a thread attempts to acquire a lock. 由于 Monitor 类具有线程关联,因此获取了 lock 的线程必须通过调用 Monitor.Exit 方法来释放 lock。Because the Monitor class has thread affinity, the thread that acquired a lock must release the lock by calling the Monitor.Exit method.

可以通过使用 Monitor.WaitMonitor.PulseMonitor.PulseAll 方法来协调用于获取同一对象上的 lock 的线程的交互。You can coordinate the interaction of threads that acquire a lock on the same object by using the Monitor.Wait, Monitor.Pulse, and Monitor.PulseAll methods.

有关详细信息,请参阅 Monitor API 参考。For more information, see the Monitor API reference.

备注

使用 C# 中的 lock 语句和 Visual Basic 中的 SyncLock 语句同步对共享资源的访问,而不是直接使用 Monitor 类。Use the lock statement in C# and the SyncLock statement in Visual Basic to synchronize access to a shared resource instead of using the Monitor class directly. 这些语句是使用 EnterExit 方法进行实现,并使用 try…finally 块来确保获取的 lock 已始终释放。Those statements are implemented by using the Enter and Exit methods and a try…finally block to ensure that the acquired lock is always released.

Mutex 类Mutex class

System.Threading.Mutex 类(与 Monitor 类似),授予对共享资源的独占访问权限。The System.Threading.Mutex class, like Monitor, grants exclusive access to a shared resource. 使用 Mutex.WaitOne 方法重载之一请求 mutex 的所有权。Use one of the Mutex.WaitOne method overloads to request the ownership of a mutex. Mutex(与 Monitor 类似)具有线程关联,并且已获取 mutex 的线程必须通过调用 Mutex.ReleaseMutex 方法来释放它。Like Monitor, Mutex has thread affinity and the thread that acquired a mutex must release it by calling the Mutex.ReleaseMutex method.

Mutex 类(与 Monitor 不同)可用于进程间同步。Unlike Monitor, the Mutex class can be used for inter-process synchronization. 为此,请使用命名 mutex,它在整个操作系统中都可见。To do that, use a named mutex, which is visible throughout the operating system. 若要创建命名 mutex 实例,请使用指定了名称的 Mutex 构造函数To create a named mutex instance, use a Mutex constructor that specifies a name. 还可以调用 Mutex.OpenExisting 方法来打开现有的命名系统 mutex。You also can call the Mutex.OpenExisting method to open an existing named system mutex.

有关详细信息,请参阅 Mutex 一文和 Mutex API 参考。For more information, see the Mutexes article and the Mutex API reference.

SpinLock 结构SpinLock structure

System.Threading.SpinLock 结构(类似于 Monitor),基于 lock 的可用性授予对共享资源的独占访问权限。The System.Threading.SpinLock structure, like Monitor, grants exclusive access to a shared resource based on the availability of a lock. SpinLock 尝试获取不可用的 lock 时,将在反复检查的循环中等待,直到 lock 变为可用。When SpinLock attempts to acquire a lock that is unavailable, it waits in a loop, repeatedly checking until the lock becomes available.

有关使用 SpinLock 的优缺点的详细信息,请参阅 SpinLock 一文和 SpinLock API 参考。For more information about the benefits and drawbacks of using spin lock, see the SpinLock article and the SpinLock API reference.

ReaderWriterLockSlim 类ReaderWriterLockSlim class

System.Threading.ReaderWriterLockSlim 类授予对共享资源的独占访问权限以便进行写入,并允许多个线程同时访问资源以便进行读取。The System.Threading.ReaderWriterLockSlim class grants exclusive access to a shared resource for writing and allows multiple threads to access the resource simultaneously for reading. 你可能想要使用 ReaderWriterLockSlim 同步对支持线程安全读取操作,但需要独占访问权限才能执行写入操作的共享数据结构的访问。You might want to use ReaderWriterLockSlim to synchronize access to a shared data structure that supports thread-safe read operations, but requires exclusive access to perform write operation. 当某个线程请求独占访问时(例如,通过调用 ReaderWriterLockSlim.EnterWriteLock 方法),后续读取器和编写器请求将被阻止,直到所有现有读取器均已退出 lock,并且编写器已进入并退出 lock。When a thread requests exclusive access (for example, by calling the ReaderWriterLockSlim.EnterWriteLock method), subsequent reader and writer requests block until all existing readers have exited the lock, and the writer has entered and exited the lock.

有关详细信息,请参阅 ReaderWriterLockSlim API 参考。For more information, see the ReaderWriterLockSlim API reference.

Semaphore 和 SemaphoreSlim 类Semaphore and SemaphoreSlim classes

System.Threading.SemaphoreSystem.Threading.SemaphoreSlim 限制可同时访问某一共享资源或资源池的线程数。The System.Threading.Semaphore and System.Threading.SemaphoreSlim classes limit the number of threads that can access a shared resource or a pool of resources concurrently. 请求资源的其他线程将等待,直到任何线程释放信号量。Additional threads that request the resource wait until any thread releases the semaphore. 由于信号量没有线程关联,因此一个线程可以获取信号量,而另一个线程可以释放它。Because the semaphore doesn't have thread affinity, a thread can acquire the semaphore and another one can release it.

SemaphoreSlimSemaphore 的轻量替代项,并且只能在单个流程边界内用于同步。SemaphoreSlim is a lightweight alternative to Semaphore and can be used only for synchronization within a single process boundary.

在 Windows 上,可以将 Semaphore 用于进程间同步。On Windows, you can use Semaphore for the inter-process synchronization. 为此,通过使用指定了名称或 Semaphore.OpenExisting 方法的 Semaphore 构造函数之一来创建表示指定了已命名系统信号量的 Semaphore 实例。To do that, create a Semaphore instance that represents a named system semaphore by using one of the Semaphore constructors that specifies a name or the Semaphore.OpenExisting method. SemaphoreSlim 不支持已命名系统信号量。SemaphoreSlim doesn't support named system semaphores.

有关详细信息,请参阅 Semaphore 和 SemaphoreSlim 一文以及 SemaphoreSemaphoreSlim API 参考。For more information, see the Semaphore and SemaphoreSlim article and the Semaphore or SemaphoreSlim API reference.

线程交互或信号Thread interaction, or signaling

线程交互(或线程信号)表示线程必须等待来自一个或多个线程的通知或信号才能继续。Thread interaction (or thread signaling) means that a thread must wait for notification, or a signal, from one or more threads in order to proceed. 例如,如果线程 A 调用线程 B 的 Thread.Join 方法,则线程 A 将被阻止,直到完成线程 B。For example, if thread A calls the Thread.Join method of thread B, thread A is blocked until thread B completes. 前面部分中所述的同步基元提供不同的信号机制:通过释放 lock,一个线程通知另一个线程可以通过获取 lock 来继续。The synchronization primitives described in the preceding section provide a different mechanism for signaling: by releasing a lock, a thread notifies another thread that it can proceed by acquiring the lock.

本部分介绍 .NET 提供的其他信号构造。This section describes additional signaling constructs provided by .NET.

EventWaitHandle、AutoResetEvent、ManualResetEvent 和 ManualResetEventSlim 类EventWaitHandle, AutoResetEvent, ManualResetEvent, and ManualResetEventSlim classes

System.Threading.EventWaitHandle 类表示一个线程同步事件。The System.Threading.EventWaitHandle class represents a thread synchronization event.

同步事件可以处于未发出信号状态或已发出信号状态。A synchronization event can be either in an unsignaled or signaled state. 当事件的状态为未发出信号时,调用了事件的 WaitOne 重载的线程会被阻止,直到事件处于已发出信号状态。When the state of an event is unsignaled, a thread that calls the event's WaitOne overload is blocked until an event is signaled. EventWaitHandle.Set 方法可将事件的状态设置为已发出信号。The EventWaitHandle.Set method sets the state of an event to signaled.

已发出信号的 EventWaitHandle 的行为取决于其重置模式:The behavior of an EventWaitHandle that has been signaled depends on its reset mode:

在 Windows 上,可以将 EventWaitHandle 用于进程间同步。On Windows, you can use EventWaitHandle for the inter-process synchronization. 为此,通过使用指定了名称或 EventWaitHandle.OpenExisting 方法的 EventWaitHandle 构造函数之一来创建表示指定了已命名系统信号量的 EventWaitHandle 实例。To do that, create a EventWaitHandle instance that represents a named system synchronization event by using one of the EventWaitHandle constructors that specifies a name or the EventWaitHandle.OpenExisting method.

有关详细信息,请参阅文章 EventWaitHandleFor more information, see the EventWaitHandle article. 对于 API 参考,请参阅 EventWaitHandleAutoResetEventManualResetEventManualResetEventSlimFor the API reference, see EventWaitHandle, AutoResetEvent, ManualResetEvent, and ManualResetEventSlim.

CountdownEvent 类CountdownEvent class

System.Threading.CountdownEvent 类表示当其计数为零时将被设置的事件。The System.Threading.CountdownEvent class represents an event that becomes set when its count is zero. CountdownEvent.CurrentCount 大于零时,调用了 CountdownEvent.Wait 的线程会被阻止。While CountdownEvent.CurrentCount is greater than zero, a thread that calls CountdownEvent.Wait is blocked. 调用 CountdownEvent.Signal 会递减事件的计数。Call CountdownEvent.Signal to decrement an event's count.

与可用于通过来自一个线程的信号取消阻止多个线程的 ManualResetEventManualResetEventSlim 相反,你可以使用 CountdownEvent 通过来自多个线程的信号取消阻止一个或多个线程。In contrast to ManualResetEvent or ManualResetEventSlim, which you can use to unblock multiple threads with a signal from one thread, you can use CountdownEvent to unblock one or more threads with signals from multiple threads.

有关详细信息,请参阅 CountdownEvent 一文和 CountdownEvent API 参考。For more information, see the CountdownEvent article and the CountdownEvent API reference.

Barrier 类Barrier class

System.Threading.Barrier 类表示线程执行屏障。The System.Threading.Barrier class represents a thread execution barrier. 调用了 Barrier.SignalAndWait 方法的线程发出信号,它已到达屏障并等待其他参与线程到达屏障。A thread that calls the Barrier.SignalAndWait method signals that it reached the barrier and waits until other participant threads reach the barrier. 当所有参与线程到达屏障时,它们将继续前进,屏障将进行重置,使之再次可用。When all participant threads reach the barrier, they proceed and the barrier is reset and can be used again.

在继续执行下一个计算阶段之前,当一个或多个线程需要其他线程的结果时,可以使用 BarrierYou might use Barrier when one or more threads require the results of other threads before proceeding to the next computation phase.

有关详细信息,请参阅 Barrier 一文和 Barrier API 参考。For more information, see the Barrier article and the Barrier API reference.

Interlocked 类Interlocked class

System.Threading.Interlocked 类提供了可对变量执行简单原子操作的静态方法。The System.Threading.Interlocked class provides static methods that perform simple atomic operations on a variable. 这些原子操作包括添加、递增和递减、交换、取决于比较的条件交换以及读取 64 位整数值的操作。Those atomic operations include addition, increment and decrement, exchange and conditional exchange that depends on a comparison, and read operation of a 64-bit integer value.

有关详细信息,请参阅 Interlocked API 参考。For more information, see the Interlocked API reference.

SpinWait 结构SpinWait structure

System.Threading.SpinWait 结构为基于自旋的等待提供支持。The System.Threading.SpinWait structure provides support for spin-based waiting. 如果线程必须等待事件收到信号或必须满足某种条件,但实际等待时间应短于使用等待句柄或以其他方式阻止线程所需的等待时间,你可能想要使用该结构。You might want to use it when a thread has to wait for an event to be signaled or a condition to be met, but when the actual wait time is expected to be less than the waiting time required by using a wait handle or by otherwise blocking the thread. 通过使用 SpinWait,你可以指定等待期间要旋转的一小段时间,且只在特定时间不满足条件时让行(例如,通过等待或休眠)。By using SpinWait, you can specify a short period of time to spin while waiting, and then yield (for example, by waiting or sleeping) only if the condition was not met in the specified time.

有关详细信息,请参阅 SpinWait 一文和 SpinWait API 参考。For more information, see the SpinWait article and the SpinWait API reference.

请参阅See also