Amalan terbaik untuk penyegerakan benang bersih

Penyegerakan adalah konsep yang digunakan untuk mengelakkan beberapa utas mengakses sumber yang dikongsi secara serentak. Anda boleh menggunakannya untuk mengelakkan beberapa utas memanggil sifat atau kaedah objek secara serentak. Yang perlu anda lakukan ialah menyegerakkan blok kod yang mengakses sumber yang dikongsi atau menyegerakkan panggilan ke sifat dan anggota objek sehingga pada satu masa tertentu hanya satu utas yang dapat memasuki bahagian kritikal.

Artikel ini memaparkan perbincangan mengenai konsep-konsep yang berkaitan dengan penyegerakan dan keselamatan benang di. Bersih dan amalan terbaik yang terlibat.

Kunci eksklusif

Penguncian eksklusif digunakan untuk memastikan bahawa pada satu-satu masa tertentu, satu dan hanya satu utas dapat memasuki bahagian kritikal. Anda perlu menggunakan salah satu daripada yang berikut untuk menerapkan kunci eksklusif dalam aplikasi anda.

  • Kunci - ini adalah jalan pintas sintaksis untuk kaedah statik kelas Monitor dan digunakan untuk memperoleh kunci eksklusif pada sumber yang dikongsi
  • Mutex - serupa dengan kata kunci kunci kecuali ia boleh berfungsi dalam pelbagai proses
  • SpinLock - digunakan untuk memperoleh kunci eksklusif pada sumber yang dikongsi dengan mengelakkan pertukaran benang konteks overhead

Anda boleh menggunakan kaedah statik kelas Monitor atau kata kunci kunci untuk menerapkan keselamatan thread dalam aplikasi anda. Kedua-dua anggota statik kelas Monitor dan kata kunci kunci dapat digunakan untuk mengelakkan akses serentak ke sumber yang dikongsi. Kata kunci kunci hanyalah cara pintas untuk melaksanakan penyegerakan. Namun, apabila anda perlu melakukan operasi yang kompleks dalam aplikasi multithreaded, kaedah Wait () dan Pulse () dari kelas Monitor dapat berguna.

Coretan kod berikut menggambarkan bagaimana anda dapat melaksanakan penyegerakan menggunakan kelas Monitor.

private static readonly object lockObj = new object();

        static void Main(string[] args)

        {

            Monitor.Enter(lockObj);

                       try

            {

               //Some code

            }

                  finally

            {

                Monitor.Exit(lockObj);

            }

        }

Kod yang setara menggunakan kata kunci kunci akan kelihatan serupa dengan ini:

    private static readonly object lockObj = new object();

        static void Main(string[] args)

        {  

            try

            {

                lock(lockObj)

                {

                    //Some code

                }             

            }

            finally

            {

                //You can release any resources here

            }

        }

Anda boleh memanfaatkan kelas Mutex untuk melaksanakan penyegerakan yang dapat merangkumi seluruh proses. Perhatikan bahawa sama dengan pernyataan kunci, kunci yang diperoleh oleh Mutex hanya dapat dilepaskan dari utas yang sama yang digunakan untuk memperoleh kunci. Memperoleh dan melepaskan kunci menggunakan Mutex relatif lebih lambat daripada melakukan yang sama menggunakan penyataan kunci.

Idea utama di sebalik SpinLock adalah untuk meminimumkan kos yang terlibat dalam pertukaran konteks antara benang - jika benang dapat menunggu atau berputar untuk beberapa lama sehingga dapat memperoleh kunci pada sumber yang dikongsi, overhead yang terlibat dalam pertukaran konteks antara utas dapat dielakkan . Apabila bahagian kritikal melakukan kerja minimum, ia boleh menjadi calon yang baik untuk SpinLock.

Kunci tidak eksklusif

Anda boleh memanfaatkan penguncian bukan eksklusif untuk membatasi serentak. Untuk melaksanakan kunci bukan eksklusif, anda boleh menggunakan salah satu daripada yang berikut.

  • Semaphore - digunakan untuk mengehadkan bilangan utas yang dapat mengakses sumber yang dikongsi bersamaan. Pada dasarnya, ia digunakan untuk membatasi jumlah pengguna untuk sumber bersama tertentu secara bersamaan.
  • SemaphoreSlim - alternatif cepat dan ringan untuk kelas Semaphore untuk melaksanakan kunci bukan eksklusif.
  • ReaderWriterLockSlim - kelas ReaderWriterLockSlim diperkenalkan di .Net Framework 3.5 sebagai pengganti kelas ReaderWriterLock.

Anda boleh menggunakan kelas ReaderWriterLockSlim untuk memperoleh kunci bukan eksklusif pada sumber yang dikongsi yang memerlukan pembacaan yang kerap tetapi kemas kini yang jarang dilakukan. Oleh itu, bukannya kunci yang saling eksklusif pada sumber yang dikongsi yang memerlukan pembacaan yang kerap dan kemas kini yang jarang dilakukan, anda boleh menggunakan kelas ini untuk memperoleh kunci baca pada sumber yang dikongsi dan kunci tulis yang eksklusif padanya.

Kebuntuan

Anda harus mengelakkan penggunaan pernyataan kunci pada jenis atau menggunakan pernyataan seperti kunci (ini) untuk melaksanakan penyegerakan dalam aplikasi anda kerana ini mungkin mengakibatkan kebuntuan. Perhatikan bahawa kebuntuan juga dapat timbul jika anda menahan kunci yang diperoleh pada sumber yang dikongsi untuk jangka masa yang lebih lama. Anda tidak boleh menggunakan jenis yang tidak berubah dalam penyata kunci anda. Sebagai contoh, anda harus mengelakkan menggunakan objek rentetan sebagai kunci dalam penyataan kunci anda. Anda harus mengelakkan penggunaan pernyataan kunci pada jenis umum - adalah amalan yang baik untuk mengunci objek peribadi atau dilindungi yang tidak diasingkan. Pada dasarnya, keadaan kebuntuan berlaku apabila banyak utas saling menunggu untuk melepaskan kunci pada sumber yang dikongsi. Anda boleh merujuk artikel MSDN ini untuk mengetahui lebih lanjut mengenai kebuntuan.