Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
System.Threading.SpinWait , çekirdek olayları için gerekli olan pahalı bağlam anahtarlarından ve çekirdek geçişlerinden kaçınmak için düşük düzeyli senaryolarda kullanabileceğiniz basit bir eşitleme türüdür. Çok çekirdekli bilgisayarlarda, bir kaynağın uzun süre tutulması beklenmiyorsa, bekleyen bir iş parçacığının birkaç düzine veya birkaç yüz döngü boyunca kullanıcı modunda dönüp ardından kaynağı tekrar almaya çalışması daha verimli olabilir. Kaynak çalıştırıldıktan sonra kullanılabilir durumdaysa, birkaç bin döngü kaydetmiş olursunuz. Kaynak hala kullanılamıyorsa, sadece birkaç döngü harcamış olursunuz ve çekirdek tabanlı bir beklemeye hala geçebilirsiniz. Bu dönen ve sonra bekleyen birleşim bazen iki aşamalı bekleme işlemi olarak adlandırılır.
SpinWait gibi çekirdek olaylarını sarmalayan .NET türleriyle birlikte kullanılacak şekilde ManualResetEventtasarlanmıştır. SpinWait tek bir programda temel döndürme işlevselliği için kendi başına da kullanılabilir.
SpinWait boş bir döngüden fazlasıdır. Genel durum için doğru döndürme davranışı sağlamak üzere dikkatle uygulanır ve yeterince uzun süre dönerse bağlam anahtarlarını başlatır (kabaca çekirdek geçişi için gereken süre). Örneğin, tek çekirdekli bilgisayarlarda, SpinWait, döndürme işlemi tüm iş parçacıklarının ilerlemesini engellediği için iş parçacığının zaman diliminden hemen feragat eder.
SpinWait ayrıca, bekleyen iş parçacığının daha yüksek öncelikli iş parçacıklarını veya çöp toplayıcıyı engellemesini önlemek için çok çekirdekli makinelerde bile verim sağlar. Bu nedenle, iki aşamalı bir bekleme işleminde bir SpinWait kullanıyorsanız, SpinWait'in kendisi bir bağlam değişimi başlatmadan önce çekirdek beklemesini çağırmanızı öneririz.
SpinWait, her NextSpinWillYield çağrısından önce denetleyebileceğiniz SpinOnce özelliğini sağlar. Özellik true döndüğünde, kendi Bekleme işleminizi başlatın. Örnek için bkz SpinWait Kullanarak Two-Phase Bekleme İşlemi Nasıl Uygulanır.
İki aşamalı bir bekleme işlemi gerçekleştirmiyor, sadece bazı koşullar doğru olana kadar dönüyorsanız, SpinWait'ün bağlam geçişlerini gerçekleştirmesini etkinleştirerek Windows işletim sistemi ortamında uyumlu olmasını sağlayabilirsiniz. Aşağıdaki temel örnek, kilitsiz bir yığında SpinWait göstermektedir. Yüksek performans gerektiren ve iş parçacıkları açısından güvenli bir yığın gerekiyorsa, System.Collections.Concurrent.ConcurrentStack<T> kullanmayı düşünün.
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