Adakah yang bisa menjelaskan perbedaan antara:
- lock (someobject) {}
- Menggunakan Mutex
- Menggunakan Semaphore
- Menggunakan Monitor
- Menggunakan kelas sinkronisasi .Net lainnya
Aku tidak bisa memahaminya. Sepertinya saya dua yang pertama sama?
Adakah yang bisa menjelaskan perbedaan antara:
Aku tidak bisa memahaminya. Sepertinya saya dua yang pertama sama?
Jawaban:
Pertanyaan yang bagus Saya mungkin salah .. Biarkan saya mencoba .. Revisi # 2 dari jawaban asal saya .. dengan sedikit lebih banyak pengertian. Terima kasih telah membuat saya membaca :)
mengunci (obj)
Monitor
Menggunakan kunci atau monitor berguna untuk mencegah eksekusi simultan blok kode yang sensitif terhadap benang, tetapi konstruksi ini tidak memungkinkan satu utas untuk mengomunikasikan suatu peristiwa ke yang lain. Ini memerlukan peristiwa sinkronisasi , yang merupakan objek yang memiliki salah satu dari dua status, yang diberi sinyal dan yang tidak ditandai, yang dapat digunakan untuk mengaktifkan dan menangguhkan utas. Mutex, Semaphores adalah konsep tingkat OS. mis. dengan nama mutex Anda dapat menyinkronkan banyak (ex) terkelola (memastikan bahwa hanya satu contoh aplikasi Anda berjalan pada mesin.)
Mutex:
Semaphores (melukai otak saya).
Monitor
komunikasi tidak dibiarkan salah; Anda masih dapat Pulse
dll denganMonitor
Re "Menggunakan kelas sinkronisasi .Net lainnya" - beberapa yang lain yang harus Anda ketahui:
Ada juga lebih banyak konstruksi penguncian (overhead rendah) di CCR / TPL ( CTP Parallel Extensions ) - tetapi IIRC, ini akan tersedia di .NET 4.0
Seperti yang dinyatakan dalam ECMA, dan seperti yang dapat Anda amati dari metode Reflected, pernyataan kunci pada dasarnya setara dengan
object obj = x;
System.Threading.Monitor.Enter(obj);
try {
…
}
finally {
System.Threading.Monitor.Exit(obj);
}
Dari contoh di atas kita melihat bahwa Monitor dapat mengunci objek.
Mutexe berguna ketika Anda membutuhkan sinkronisasi antar proses karena mereka dapat mengunci pengenal string. Pengidentifikasi string yang sama dapat digunakan oleh berbagai proses untuk mendapatkan kunci.
Semaphore seperti Mutex pada steroid, mereka memungkinkan akses bersamaan dengan memberikan jumlah maksimum akses bersamaan '. Setelah batas tercapai, semaphore mulai memblokir akses lebih lanjut ke sumber daya sampai salah satu penelepon melepaskan semaphore.
Saya melakukan dukungan kelas & CLR untuk threading di DotGNU dan saya punya beberapa pemikiran ...
Kecuali Anda membutuhkan kunci proses silang, Anda harus selalu menghindari penggunaan Mutex & Semaphores. Kelas-kelas ini dalam. NET adalah pembungkus di sekitar Win32 Mutex dan Semaphores dan agak berat (mereka membutuhkan konteks switch ke Kernel yang mahal - terutama jika kunci Anda tidak dalam pertikaian).
Seperti yang lain disebutkan, pernyataan kunci C # adalah sihir kompiler untuk Monitor.Enter dan Monitor.Exit (ada dalam coba / akhirnya).
Monitor memiliki mekanisme sinyal / tunggu sederhana namun kuat yang tidak dimiliki Mutex melalui metode Monitor.Pulse / Monitor.Wait. Setara Win32 akan menjadi objek acara melalui CreateEvent yang sebenarnya juga ada di .NET sebagai WaitHandles. Model Pulse / Wait mirip dengan pthread_signal dan pthread_wait Unix tetapi lebih cepat karena mereka bisa sepenuhnya operasi mode pengguna dalam kasus un-contended.
Monitor.Pulse / Tunggu mudah digunakan. Dalam satu utas, kita mengunci objek, memeriksa bendera / negara bagian / properti dan jika bukan itu yang kita harapkan, hubungi Monitor. Tunggu yang akan melepaskan kunci dan tunggu sampai pulsa dikirim. Ketika menunggu kembali, kami kembali dan memeriksa kembali flag / state / property. Di utas lainnya, kita mengunci objek setiap kali kita mengubah flag / state / property dan kemudian memanggil PulseAll untuk membangunkan utas dengar.
Seringkali kita ingin agar kelas kita aman dari benang sehingga kita memasukkan kunci ke dalam kode kita. Namun, sering terjadi bahwa kelas kita hanya akan digunakan oleh satu utas. Ini berarti kunci tidak perlu memperlambat kode kami ... ini adalah di mana optimisasi cerdas dalam CLR dapat membantu meningkatkan kinerja.
Saya tidak yakin tentang penerapan kunci Microsoft tetapi di DotGNU dan Mono, bendera negara kunci disimpan di header setiap objek. Setiap objek di .NET (dan Java) dapat menjadi kunci sehingga setiap objek perlu mendukung ini di header mereka. Dalam implementasi DotGNU, ada bendera yang memungkinkan Anda untuk menggunakan hashtable global untuk setiap objek yang digunakan sebagai kunci - ini memiliki manfaat menghilangkan overhead 4 byte untuk setiap objek. Ini tidak bagus untuk memori (terutama untuk sistem tertanam yang tidak sangat berulir) tetapi memiliki kinerja yang baik.
Baik Mono dan DotGNU secara efektif menggunakan mutex untuk melakukan penguncian / menunggu tetapi menggunakan operasi perbandingan-dan-pertukaran gaya spinlock untuk menghilangkan kebutuhan untuk benar-benar melakukan kunci keras kecuali benar-benar diperlukan:
Anda dapat melihat contoh bagaimana monitor dapat diterapkan di sini:
http://cvs.savannah.gnu.org/viewvc/dotgnu-pnet/pnet/engine/lib_monitor.c?revision=1.7&view=markup
Peringatan tambahan untuk mengunci Mutex bersama yang Anda identifikasi dengan string ID adalah bahwa itu akan default ke mutex "Lokal \" dan tidak akan dibagikan di seluruh sesi di lingkungan server terminal.
Awali pengenal string Anda dengan "Global \" untuk memastikan bahwa akses ke sumber daya sistem bersama dikontrol dengan benar. Saya baru saja mengalami sejumlah masalah sinkronisasi komunikasi dengan layanan yang berjalan di bawah akun SYSTEM sebelum saya menyadari hal ini.
Saya akan mencoba untuk menghindari "kunci ()", "Mutex" dan "Monitor" jika Anda dapat ...
Lihat namespace System.Collections.Concurrent di .NET 4 yang baru
ini memiliki beberapa kelas koleksi thread-safe yang bagus
http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx
Batu ConcurrentDictionary! tidak ada penguncian manual lagi untuk saya!
Dalam kebanyakan kasus, Anda tidak boleh menggunakan kunci (= Monitor) atau mutex / semaphores. Mereka semua memblokir utas saat ini.
Dan kamu pasti tidak boleh menggunakan System.Collections.Concurrent
kelas - mereka adalah sumber utama kondisi lomba karena tidak mendukung transaksi antara banyak koleksi, dan juga memblokir utas saat ini.
Anehnya .NET tidak memiliki mekanisme sinkronisasi yang efektif.
Saya menerapkan antrian serial dari GCD ( Objc/Swift
dunia) di C # - sangat ringan, tidak menghalangi alat sinkronisasi yang menggunakan kumpulan benang, dengan pengujian.
Ini adalah cara terbaik untuk menyinkronkan apa pun dalam banyak kasus - dari akses basis data (halo sqlite) ke logika bisnis.