Sanırım optimizer, isCompletedeğişkendeki 'uçucu' anahtar kelimenin olmaması nedeniyle kandırılıyor .
Elbette ekleyemezsiniz çünkü bu yerel bir değişken. Ve tabii ki, yerel bir değişken olduğu için buna hiç ihtiyaç duyulmamalıdır, çünkü yerliler yığın halinde tutulur ve doğal olarak her zaman "taze" dir.
Ancak , derledikten sonra artık yerel bir değişken değildir . Anonim bir temsilciden erişildiğinden, kod bölünür ve aşağıdaki gibi bir yardımcı sınıfa ve üye alanına çevrilir:
public static void Main(string[] args)
{
TheHelper hlp = new TheHelper();
var t = new Thread(hlp.Body);
t.Start();
Thread.Sleep(500);
hlp.isComplete = true;
t.Join();
Console.WriteLine("complete!");
}
private class TheHelper
{
public bool isComplete = false;
public void Body()
{
int i = 0;
while (!isComplete) i += 0;
}
}
Artık çok iş parçacıklı bir ortamdaki JIT derleyicisinin / optimize edicisinin, TheHelpersınıfı işlerken , aslında yöntemin başlangıcında bir yazmaç veya yığın çerçevesindeki değeri önbelleğe alabileceğini ve yöntem bitene kadar asla yenilemeyeceğini hayal edebiliyorum . Bunun nedeni, iş parçacığı ve yöntemin "= true" çalıştırılmadan SONA ERMEYECEĞİNİN HİÇBİR GARANTİSİ olmamasıdır, bu yüzden garanti yoksa, neden önbelleğe almayasınız ve yığın nesnesini her seferinde okumak yerine bir kez okuyarak performans artışı elde etmeyiniz. yineleme.falseBody()
Anahtar kelimenin volatilevar olmasının nedeni budur .
Bu yardımcı sınıf olabilmesi için doğru bir minik daha iyi bit 1) çok kanallı ortamlarda, bu olmalıdır:
public volatile bool isComplete = false;
ancak elbette, otomatik olarak oluşturulmuş kod olduğu için ekleyemezsiniz. Daha iyi bir yaklaşım, lock()okuma ve yazma işlemlerinin etrafına bazı metinler eklemek isCompletedveya bunu çıplak metal yapmaya çalışmak yerine kullanıma hazır diğer bazı senkronizasyon veya iş parçacığı / görevlendirme yardımcı programlarını kullanmak olacaktır (çıplak metal olmayacaktır , CLR'de GC, JIT ve (..) ile C # olduğundan).
Hata ayıklama modundaki fark büyük olasılıkla hata ayıklama modunda birçok optimizasyonun hariç tutulması nedeniyle oluşur, böylece ekranda gördüğünüz kodda hata ayıklayabilirsiniz. Bu nedenle while (!isComplete), orada bir kesme noktası ayarlayabileceğiniz için optimize edilmemiştir ve bu nedenle isComplete, yöntemin başlangıcında bir yazmaçta veya yığında agresif bir şekilde önbelleğe alınmaz ve her döngü yinelemesinde öbek üzerindeki nesneden okunur.
BTW. Bu sadece benim tahminlerim. Derlemeye bile çalışmadım.
BTW. Bir hata gibi görünmüyor; daha çok belirsiz bir yan etkiye benziyor. Ayrıca, bu konuda haklıysam, bu bir dil eksikliği olabilir - C #, yakalanan ve kapanışlarda üye alanlara yükseltilen yerel değişkenlere 'geçici' anahtar kelime yerleştirmeye izin vermelidir.
1) yaklaşık Eric Lippert bir yorumlar için aşağıya bakın volatileve / veya güvenerek bu kodu sağlamada karmaşayı seviyelerini gösteren bu çok ilginç makale volatileolan güvenli ..uh, iyi ..uh, en Tamam diyelim.