Bolehkah Nilai Cached pada Thread Mengabaikan Perubahan yang Dibuat pada Thread Lain?
Soalan ini memfokuskan sama ada thread C# boleh cache nilai dan mengabaikan perubahan seterusnya yang dibuat kepada nilai itu pada urutan yang berbeza. Walaupun pengetahuan umum tentang keadaan perlumbaan, atomicity dan penggunaan kunci, siasatan khusus menyasarkan senario di mana masa jalan .NET mungkin berpotensi menghilangkan kebimbangan memori yang tidak menentu.
Sesetengah sumber mendakwa bahawa dalam kod berikut, bacaan thread mungkin menyimpan nilai awal pembolehubah bool "berhenti" dan tidak pernah mengesan pengubahsuaiannya, yang berpotensi membawa kepada infiniti gelung:
class BackgroundTaskDemo { private bool stopping = false; static void Main() { BackgroundTaskDemo demo = new BackgroundTaskDemo(); new Thread(demo.DoWork).Start(); Thread.Sleep(5000); demo.stopping = true; } static void DoWork() { while (!stopping) { // Do something here } } }
Walau bagaimanapun, kesahihan tuntutan ini dipertikaikan. Pengkritik mempersoalkan sama ada masa jalan .NET akan benar-benar mengabaikan perubahan pada nilai memori seperti yang didakwa. Mereka menunjukkan bahawa kod yang diberikan "hampir pasti" berfungsi, membayangkan bahawa tuntutan itu tidak berasas.
Inti perkara ini ialah tingkah laku yang diterangkan dalam tuntutan itu tidak dijamin oleh spesifikasi .NET. Walaupun ia mungkin berfungsi dalam kebanyakan kes, ia tidak dipastikan untuk melakukannya dalam semua keadaan. Pakar dalam bidang model ingatan berhati-hati daripada bergantung pada hasil yang tidak boleh dipercayai seperti itu.
Selain itu, contoh balas yang boleh disahkan telah dibentangkan, menunjukkan senario tertentu di mana kod gagal seperti yang diramalkan. Dalam kod yang disemak berikut, "berhenti" diisytiharkan sebagai tidak menentu untuk membetulkan isu:
using System.Threading; using System; static class BackgroundTaskDemo { // make this volatile to fix it private static bool stopping = false; static void Main() { new Thread(DoWork).Start(); Thread.Sleep(5000); stopping = true; Console.WriteLine("Main exit"); Console.ReadLine(); } static void DoWork() { int i = 0; while (!stopping) { i++; } Console.WriteLine("DoWork exit " + i); } }
Apabila dijalankan dalam mod "pelepasan" tanpa kata kunci yang tidak menentu, kod tersebut memasuki gelung tak terhingga dan terus berjalan selama-lamanya, walaupun selepas "berhenti" telah ditetapkan kepada benar. Walau bagaimanapun, menambah "tidak menentu" pada pembolehubah "berhenti" menyelesaikan isu, membenarkan gelung keluar seperti yang dimaksudkan.
Kesimpulannya ialah walaupun kod itu mungkin kelihatan berfungsi, ia tidak boleh dijamin untuk berbuat demikian. secara konsisten. Untuk kod berbilang benang yang mantap dan boleh dipercayai, penggunaan kunci atau kata kunci yang tidak menentu adalah amat dinasihatkan.
Atas ialah kandungan terperinci Bolehkah C# Threads Cache Nilai Boolean dan Abaikan Perubahan Seterusnya pada Thread Lain?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!