返回介绍

SpinWait

发布于 2025-02-23 23:16:14 字数 2892 浏览 0 评论 0 收藏 0

System.Threading.SpinWait 是可以在低级别方案中使用,以避免昂贵的上下文切换和内核转换所需的内核事件的轻量同步类型。 在多核计算机上时资源不需要容纳较长时间,它可以是时间的正在等待的线程几个装入数十或几个几百个周期,在用户模式下启动,然后重试获取该资源对于更加高效。 如果资源在旋转后变为可用,则可以节省数千个周期。 如果资源是仍不可用,然后你所用仅几个周期,并仍然可以输入基于内核的等待。 此旋转然后等待组合有时称为两阶段等待操作

SpinWait 旨在与.NET Framework 类型,如简单包装内核事件结合使用 ManualResetEvent 。 SpinWait 此外可通过本身只在一个程序中的基本旋转功能。

SpinWait 远不止一个空的循环。 仔细实现以提供的一般情况下,正确的旋转行为,而且会本身执行上下文切换在旋转足够长的时间 (大约内核转换所需的时间长度)。 例如,在单核计算机 SpinWait 产生线程的时间片立即因为旋转块转发所有线程上的进度。 SpinWait 此外会产生甚至在多核计算机,以防止阻止更高优先级的线程或垃圾回收器正在等待的线程上。 因此,如果你使用 SpinWait 在两阶段等待操作中,我们建议调用之前在内核等待 SpinWait 本身启动的上下文切换。 SpinWait 提供 NextSpinWillYield 属性,可以在每次调用之前检查 SpinOnce 。 当该属性返回 true ,启动你自己的等待操作。 有关示例,请参阅 如何: 使用 SpinWait 实现两阶段等待操作 。

如果你不执行两阶段等待操作,但只旋转直到某些条件为 true,则可以启用 SpinWait 执行其上下文切换,以便它是在 Windows 操作系统环境中的一个好公民。 下面的基本示例演示 SpinWait 无锁堆栈中。 如果你需要高性能、 线程安全的堆栈,请考虑使用 System.Collections.Concurrent.ConcurrentStack<T> 。

public class LockFreeStack<T>
{
  private volatile Node m_head;

  private class Node { public Node Next; public T Value; }

  public void Push(T item)
  {
    var spin = new SpinWait();
    Node node = new Node { Value = item }, head;
    while (true)
    {
      head = m_head;
      node.Next = head;
      if (Interlocked.CompareExchange(ref m_head, node, head) == head) break;
      spin.SpinOnce();
    }
  }

  public bool TryPop(out T result)
  {
    result = default(T);
    var spin = new SpinWait();

    Node head;
    while (true)
    {
      head = m_head;
      if (head == null) return false;
      if (Interlocked.CompareExchange(ref m_head, head.Next, head) == head)
      {
        result = head.Value;
        return true;
      }
      spin.SpinOnce();
    }
  }
}
Imports System.Threading
Module SpinWaitDemo


  Public Class LockFreeStack(Of T)
    Private m_head As Node

    Private Class Node
      Public [Next] As Node
      Public Value As T
    End Class

    Public Sub Push(ByVal item As T)
      Dim spin As New SpinWait()
      Dim head As Node, node As New Node With {.Value = item}

      While True
        Thread.MemoryBarrier()
        head = m_head
        node.Next = head
        If Interlocked.CompareExchange(m_head, node, head) Is head Then Exit While
        spin.SpinOnce()
      End While
    End Sub

    Public Function TryPop(ByRef result As T) As Boolean
      result = CType(Nothing, T)
      Dim spin As New SpinWait()

      Dim head As Node
      While True
        Thread.MemoryBarrier()
        head = m_head
        If head Is Nothing Then Return False
        If Interlocked.CompareExchange(m_head, head.Next, head) Is head Then
          result = head.Value
          Return True
        End If
        spin.SpinOnce()
      End While
    End Function
  End Class


End Module

另请参阅

SpinWait
线程处理对象和功能

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文