Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
System.Threading.SpinWait adalah jenis sinkronisasi ringan yang dapat Anda gunakan dalam skenario tingkat rendah untuk menghindari sakelar konteks dan transisi kernel yang mahal yang diperlukan untuk peristiwa kernel. Pada komputer multicore, ketika sumber daya tidak diharapkan ditahan untuk jangka waktu yang lama, mungkin lebih efisien bagi utas tunggu untuk berputar dalam mode pengguna selama beberapa lusin atau beberapa ratus siklus, dan kemudian mencoba lagi untuk memperoleh sumber daya. Jika sumber daya tersedia setelah berputar, maka Anda telah menghemat beberapa ribu siklus. Jika sumber daya masih belum tersedia, maka Anda hanya menghabiskan beberapa siklus dan masih dapat memasuki keadaan tunggu berbasis kernel. Kombinasi berputar-kemudian-menunggu ini kadang-kadang disebut sebagai operasi tunggu dua fase.
SpinWait dirancang untuk digunakan bersama dengan jenis .NET yang membungkus peristiwa kernel seperti ManualResetEvent. SpinWait juga dapat digunakan dengan sendirinya untuk fungsi pemintalan dasar dalam hanya satu program.
SpinWait lebih dari sekadar perulangan kosong. Ini diimplementasikan dengan hati-hati untuk memberikan perilaku berputar yang benar untuk kasus pada umumnya, dan akan memulai sendiri peralihan konteks jika berputar cukup lama (kira-kira waktu yang dibutuhkan untuk transisi kernel). Misalnya, pada komputer inti tunggal, SpinWait memberikan waktu eksekusi pada utas segera karena memutar dapat menghentikan kemajuan pada semua utas.
SpinWait juga berfungsi bahkan pada komputer multi-inti untuk mencegah thread tunggu memblokir thread prioritas yang lebih tinggi atau pengumpul sampah. Oleh karena itu, jika Anda menggunakan SpinWait dalam operasi tunggu dua fase, kami sarankan Anda memanggil kernel tunggu sebelum SpinWait itu sendiri memulai pergantian konteks.
SpinWait menyediakan properti NextSpinWillYield, yang dapat Anda periksa sebelum setiap panggilan ke SpinOnce. Saat properti mengembalikan true, mulai operasi Tunggu Anda sendiri. Misalnya, lihat Cara: Menggunakan SpinWait untuk Menerapkan Operasi Tunggu Two-Phase.
Jika Anda tidak melakukan operasi tunggu dua fase tetapi hanya berputar sampai beberapa kondisi benar, Anda dapat mengaktifkan SpinWait untuk melakukan sakelar konteksnya sehingga merupakan warga negara yang baik di lingkungan sistem operasi Windows. Contoh dasar berikut menunjukkan sebuah SpinWait yang ada dalam tumpukan bebas kunci. Jika Anda memerlukan tumpukan berkinerja tinggi, dan aman terhadap utas, pertimbangkan untuk menggunakan 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