Dua sen saya di SpinLock di .Net

Bayangkan keadaan di mana utas cuba mendapatkan akses ke sumber yang dikongsi tetapi sumbernya sudah terkunci, jadi utas harus menunggu sehingga kunci dilepaskan. Di sinilah penyegerakan utas dimainkan. Penyegerakan benang digunakan untuk mengelakkan beberapa utas mengakses sumber yang dikongsi secara serentak. Rangka Kerja Microsoft .Net memberikan sokongan untuk pelbagai primitif penyegerakan yang dapat digunakan untuk mengawal tingkah laku utas dan menghindari keadaan perlumbaan. Mutex dan Spinlock adalah dua mekanisme penyegerakan yang popular yang digunakan untuk menyegerakkan akses ke sumber yang dikongsi.

SpinLock adalah alternatif untuk menyekat penyegerakan. SpinLock (juga dikenal sebagai "Busy Waiting") adalah mekanisme yang dapat digunakan untuk membuat benang yang berusaha mendapatkan kunci tunggu dalam satu gelung sehingga dapat memperoleh akses ke sumber. Perhatikan bahawa SpinLock dapat berkinerja lebih cepat berbanding Mutex kerana pertukaran konteks dikurangkan. Walau bagaimanapun, anda harus menggunakan SpinLocks hanya jika bahagian kritikal sepatutnya melakukan sedikit kerja, iaitu, SpinLock diadakan untuk jangka waktu yang sangat singkat. SpinLocks biasanya lebih disukai dalam sistem multiprosesor simetri untuk sentiasa membuat tinjauan untuk ketersediaan sumber sebagai pengganti pertukaran konteks.

Apa itu SpinLock dan mengapa ia diperlukan?

SpinLock melakukan penantian yang sibuk dan dapat menawarkan prestasi yang lebih baik ketika digunakan dalam sistem multi-teras terutama ketika menunggu dengan cepat dan mengumpulkan sumber daripada menyekatnya. Ini sangat berguna apabila masa penahan kunci dalam jangka masa pendek. Dengan kata lain, anda boleh memanfaatkan SpinLock dalam sistem multi-teras untuk mengurangkan overhead yang terlibat dalam pertukaran konteks jika masa yang akan dihabiskan di bahagian kritikal adalah kecil. Bahagian kritikal boleh didefinisikan sebagai struktur data atau sumber yang dikongsi oleh beberapa utas tetapi satu dan hanya satu utas dapat mengaksesnya pada suatu waktu tertentu.

Harus diingat bahawa menahan SpinLock untuk jangka masa yang lebih lama hanya akan membuang sumber daya sistem dan merugikan prestasi aplikasi. Pada hakikatnya, jika anda menjangkakan penyekatan itu mempunyai jangka masa yang signifikan, SpinLock tidak boleh digunakan - gunakan SpinLock hanya apabila masa penahan kunci dalam jangka masa yang agak kecil.

SpinLock biasanya digunakan ketika bekerja dengan interupsi untuk melakukan penantian yang sibuk di dalam gelung sehingga sumber tersedia. SpinLock tidak menyebabkan utas diutamakan, sebaliknya, ia terus berputar sehingga kunci sumber dilepaskan.

Pengaturcaraan SpinLock in .Net

Perhatikan bahawa SpinLock didefinisikan sebagai struktur dalam .Net, iaitu, ia didefinisikan sebagai jenis nilai untuk alasan prestasi. Oleh itu, jika anda menyebarkan contoh SpinLock, anda harus meneruskannya dengan merujuk dan bukan berdasarkan nilai. Di bahagian ini kita akan menerangkan bagaimana kita dapat memprogram SpinLock di .Net. Untuk melaksanakan SpinLock in .Net, anda perlu memanfaatkan kelas SpinLock yang terdapat di System. Threading namespace.

Penyenaraian kod berikut menunjukkan bagaimana anda boleh 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();

}

Tunggu

Perhatikan bahawa seperti SpinLock, SpinWait juga merupakan struktur dan bukan kelas. Sama dengan SpinLock, anda boleh menggunakan SpinWait untuk menulis kod penyegerakan bebas kunci yang boleh "berputar" dan bukannya menyekat. SpinWait dapat digunakan untuk mengurangi penggunaan sumber 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 bilangan lelaran yang tetap. MSDN menyatakan: "System.Threading.SpinWait adalah jenis penyegerakan ringan yang boleh anda gunakan dalam senario peringkat rendah untuk mengelakkan suis konteks mahal dan peralihan kernel yang diperlukan untuk peristiwa kernel."

Untuk menggunakan SpinWait dalam kod anda, anda boleh memanfaatkan kaedah statik SpinUntil () dari struktur SpinWait, atau, memanfaatkan kaedahnya yang tidak statik SpinOnce (). Coretan kod berikut menggambarkan bagaimana SpinWait dapat digunakan.

SpinWait spinWait = new SpinWait();

bool shouldSpin;

while (!shouldSpin)

{

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

}