Ada banyak pertanyaan disini. Mempertimbangkannya satu per satu:
tugas referensi adalah atom jadi mengapa Interlocked.Exchange (ref Object, Object) diperlukan?
Tugas referensi bersifat atom. Interlocked.Exchange tidak hanya melakukan tugas referensi. Itu membaca nilai saat ini dari variabel, menyembunyikan nilai lama, dan memberikan nilai baru ke variabel, semua sebagai operasi atom.
kolega saya mengatakan bahwa pada beberapa platform, tidak ada jaminan bahwa penetapan referensi bersifat atomik. Apakah kolega saya benar?
Tidak. Penetapan referensi dijamin sepenuhnya di semua platform .NET.
Rekan saya berpikir dari premis yang salah. Apakah itu berarti kesimpulan mereka salah?
Belum tentu. Kolega Anda mungkin memberi Anda nasihat yang baik untuk alasan yang buruk. Mungkin ada beberapa alasan lain mengapa Anda harus menggunakan Interlocked.Exchange. Pemrograman bebas kunci sangat sulit dan saat Anda menyimpang dari praktik mapan yang didukung oleh para ahli di bidangnya, Anda berada dalam bahaya dan mengambil risiko kondisi balapan yang paling buruk. Saya bukan ahli di bidang ini atau ahli kode Anda, jadi saya tidak dapat membuat penilaian dengan satu atau lain cara.
menghasilkan peringatan "referensi ke kolom volatile tidak akan diperlakukan sebagai volatile" Apa yang harus saya pikirkan tentang ini?
Anda harus memahami mengapa ini menjadi masalah secara umum. Itu akan mengarah pada pemahaman tentang mengapa peringatan itu tidak penting dalam kasus khusus ini.
Alasan kompilator memberikan peringatan ini adalah karena menandai bidang sebagai volatile berarti "bidang ini akan diperbarui pada beberapa utas - jangan buat kode apa pun yang menyimpan nilai bidang ini, dan pastikan bahwa setiap membaca atau menulis bidang ini tidak "dipindahkan ke depan dan ke belakang dalam waktu" melalui inkonsistensi cache prosesor. "
(Saya berasumsi bahwa Anda sudah memahami semua itu. Jika Anda tidak memiliki pemahaman terperinci tentang arti volatile dan bagaimana pengaruhnya terhadap semantik cache prosesor, maka Anda tidak memahami cara kerjanya dan tidak boleh menggunakan volatile. Program bebas kunci sangat sulit untuk dilakukan dengan benar; pastikan bahwa program Anda benar karena Anda memahami cara kerjanya, bukan secara tidak sengaja.)
Sekarang misalkan Anda membuat variabel yang merupakan alias dari bidang yang mudah menguap dengan mengirimkan ref ke bidang itu. Di dalam metode yang dipanggil, kompilator tidak memiliki alasan apa pun untuk mengetahui bahwa referensi harus memiliki semantik volatil! Kompilator dengan senang hati akan menghasilkan kode untuk metode yang gagal menerapkan aturan untuk bidang volatil, tetapi variabelnya adalah bidang volatil. Itu benar-benar dapat merusak logika bebas kunci Anda; asumsinya selalu bahwa bidang volatile selalu diakses dengan semantik volatile. Tidak masuk akal untuk memperlakukannya sebagai volatile kadang-kadang dan tidak di lain waktu; Anda harus selalu konsisten jika tidak, Anda tidak dapat menjamin konsistensi pada akses lain.
Oleh karena itu, kompilator memperingatkan ketika Anda melakukan ini, karena itu mungkin akan mengacaukan sepenuhnya logika bebas kunci yang dikembangkan dengan hati-hati.
Tentu saja, Interlocked.Exchange yang ditulis untuk mengharapkan bidang yang mudah menguap dan melakukan hal yang benar. Oleh karena itu, peringatan tersebut menyesatkan. Saya sangat menyesali ini; yang seharusnya kita lakukan adalah mengimplementasikan beberapa mekanisme di mana penulis metode seperti Interlocked.Exchange dapat meletakkan atribut pada metode yang mengatakan "metode ini yang mengambil ref memaksakan semantik volatil pada variabel, jadi tekan peringatannya". Mungkin dalam versi kompilator yang akan datang kami akan melakukannya.
var myresult = await Task.Factory.CreateNew(() => MyWork(exclusivelyLocalStuffOrValueTypeOrCopy));
.Mungkin kolega Anda salah, atau dia tahu sesuatu yang tidak diketahui oleh spesifikasi bahasa C #.
5.5 Atomitas referensi variabel :
Jadi, Anda dapat menulis ke referensi yang mudah menguap tanpa risiko mendapatkan nilai yang rusak.
Anda tentunya harus berhati-hati dengan cara Anda memutuskan utas mana yang harus mengambil data baru, untuk meminimalkan risiko bahwa lebih dari satu utas pada satu waktu melakukannya.
sumber
Interlocked.Exchange <T>
Itu mengubah dan mengembalikan nilai aslinya, tidak berguna karena Anda hanya ingin mengubahnya dan, seperti yang dikatakan Guffa, itu sudah atom.
Kecuali jika seorang profiler terbukti menjadi penghambat dalam aplikasi Anda, Anda harus mempertimbangkan kunci unsing, lebih mudah untuk memahami dan membuktikan bahwa kode Anda benar.
sumber
Iterlocked.Exchange()
tidak hanya atom, tetapi juga menjaga visibilitas memori:Masalah Sinkronisasi dan Multiprosesor
Ini berarti bahwa selain atomisitas, ini memastikan bahwa:
sumber