Dua sen saya di SpinLock di .Net

Bayangkan situasi di mana utas mencoba mendapatkan akses ke sumber daya bersama tetapi sumber daya sudah terkunci, jadi utas harus menunggu hingga kunci dilepaskan. Di sinilah sinkronisasi utas berperan. Sinkronisasi utas digunakan untuk mencegah beberapa utas mengakses sumber daya bersama secara bersamaan. Microsoft .Net Framework menyediakan dukungan untuk berbagai sinkronisasi primitif yang dapat digunakan untuk mengontrol perilaku utas dan menghindari kondisi balapan. Mutex dan Spinlock adalah dua mekanisme sinkronisasi populer yang digunakan untuk menyinkronkan akses ke sumber daya bersama.

SpinLock adalah alternatif untuk memblokir sinkronisasi. SpinLock (juga dikenal sebagai "Busy Waiting") adalah mekanisme yang dapat digunakan untuk membuat utas mencoba mendapatkan kunci menunggu dalam satu lingkaran hingga bisa mendapatkan akses ke sumber daya. Perhatikan bahwa SpinLock dapat bekerja lebih cepat dibandingkan dengan Mutex karena pengalihan konteks berkurang. Namun, Anda harus menggunakan SpinLock hanya jika bagian kritis seharusnya melakukan sedikit pekerjaan, yaitu, SpinLock ditahan untuk waktu yang sangat singkat. SpinLocks biasanya lebih disukai dalam sistem multiprosesor simetris untuk terus-menerus melakukan polling ketersediaan sumber daya sebagai pengganti sakelar konteks.

Apa itu SpinLock dan mengapa itu dibutuhkan?

SpinLock melakukan penantian sibuk dan dapat menawarkan kinerja yang lebih baik bila digunakan dalam sistem multi-inti terutama bila menunggu dalam satu lingkaran dan mengumpulkan sumber daya lebih murah daripada memblokirnya. Ini sangat membantu ketika waktu penahanan kunci memiliki durasi yang singkat. Dengan kata lain, Anda dapat memanfaatkan SpinLock dalam sistem multi-core untuk mengurangi overhead yang terlibat dalam pengalihan konteks jika waktu yang dihabiskan di dalam bagian kritis kecil. Bagian penting dapat didefinisikan sebagai struktur data atau sumber daya yang digunakan bersama oleh beberapa utas tetapi satu dan hanya satu utas yang dapat memiliki akses ke sana pada titik waktu tertentu.

Perlu dicatat bahwa memegang SpinLock untuk durasi yang lebih lama hanya akan membuang-buang sumber daya sistem dan merusak kinerja aplikasi. Intinya, jika Anda berharap pemblokiran berlangsung dalam durasi yang signifikan, SpinLock tidak boleh digunakan - gunakan SpinLock hanya jika waktu penahanan kunci dalam durasi yang cukup kecil.

SpinLock biasanya digunakan saat bekerja dengan interupsi untuk melakukan penantian sibuk di dalam loop sampai sumber daya tersedia. SpinLock tidak menyebabkan utas didahului, melainkan terus berputar sampai kunci pada sumber daya dilepaskan.

Pemrograman SpinLock di .Net

Perhatikan bahwa SpinLock didefinisikan sebagai struct di .Net, yaitu didefinisikan sebagai tipe nilai untuk alasan kinerja. Karenanya, jika Anda membagikan instance SpinLock, Anda harus meneruskannya dengan referensi dan bukan dengan nilai. Pada bagian ini kita akan membahas bagaimana kita dapat memprogram SpinLock di .Net. Untuk mengimplementasikan SpinLock di .Net, Anda perlu memanfaatkan kelas SpinLock yang tersedia di namespace System.Threading.

Daftar kode berikut menunjukkan bagaimana Anda dapat menggunakan SpinLock di .Net.

SpinLock spinLock = new SpinLock (true);

bool isLocked = false;

try

{

spinLock.Enter (ref isLocked);

// Write your usual code here

}

finally

{

if (isLocked)

   spinLock.Exit();

}

SpinWait

Perhatikan bahwa seperti SpinLock, SpinWait juga merupakan struct dan bukan kelas. Mirip dengan SpinLock, Anda dapat menggunakan SpinWait untuk menulis kode sinkronisasi bebas kunci yang dapat "berputar" daripada memblokir. SpinWait dapat digunakan untuk mengurangi konsumsi sumber daya dengan melakukan pemintalan intensif CPU untuk 10 pos iterasi yang akan menghasilkan kontrol dengan memanggil Thread.Yield dan Thread.Sleep. Dengan kata lain, SpinWait dapat digunakan untuk membatasi pemintalan intensif CPU ke sejumlah iterasi yang tetap. MSDN menyatakan: "System.Threading.SpinWait adalah jenis sinkronisasi ringan yang dapat Anda gunakan dalam skenario tingkat rendah untuk menghindari sakelar konteks yang mahal dan transisi kernel yang diperlukan untuk acara kernel."

Untuk menggunakan SpinWait dalam kode Anda, Anda dapat memanfaatkan metode statis SpinUntil () dari struct SpinWait, atau, memanfaatkan metode non-statis SpinOnce (). Potongan kode berikut menggambarkan bagaimana SpinWait dapat digunakan.

SpinWait spinWait = new SpinWait();

bool shouldSpin;

while (!shouldSpin)

{

   Thread.MemoryBarrier(); spinWait.SpinOnce();

}