Soru Referans ataması threadafe midir?


Araba nesnelerinin bir listesini tutacak C # 'da çok iş parçacıklı bir önbellek yapıyorum:

public static IList<Car> Cars {get; private set;}

Kilitli olmayan bir iş parçasında referansı değiştirmenin güvenli olup olmadığını merak ediyorum.

Örneğin.

private static void Loop()
{
  while (true)
  {
    Cars = GetFreshListFromServer();
    Thread.Sleep(SomeInterval);
  }
}

Temel olarak, Cars'a yeni bir referans atamanın atomik olup olmadığına ya da tahmin edemeyeceğime iner.

Eğer değilse, arabalarım için özel bir alan kullanmam gerekecek.


32
2018-03-06 09:06


Menşei


Bir yan not olarak, bir static liste mutasyon sorunlarına duyarlı olacak; onu kilitlerin dışında değiştirmeyin! - Marc Gravell♦
İyi nokta, muhtemelen bir özel get ile biter ve bir kopyasını veya salt okunur sürümünü döneceğim. - Steffen
Bir yan notta, O (1) arama süresini artırmak ve eşzamanlılığı yönetmek için bir ConcurrentDictionary <Araba, Araba> kullanmayı düşündünüz mü? Ayrıca, gerçekten sadece bir iş parçacığının listeyi yenilemesini sağlamalısınız. Aksi takdirde gerekenden daha fazla ağ araması yapıyor olacaksınız. - Josh Smeaton
Bunu dikkate almadım. Oldukça düzgün görünüyor ve aramalar için <int, Car> sözüne ihtiyacım olabilir, bu nedenle bu kullanışlı olabilir. Yenilemeye gelince, iş parçacığını statik bir yapıcıda ürettim, böylece yalnızca bir tane olacak. - Steffen


Cevaplar:


Evet, referans güncellemelerinin dil özelliğinde atomik olması garanti edilir.

5.5 Değişken referansların atomikliği

Aşağıdaki veri türlerinin okuma ve yazma işlemleri atomiktir: bool, char, byte, sbyte, kısa, ushort, uint, int, float ve referans türleri. Ayrıca, önceki listede yer alan bir türdeki yazı tiplerinin okur ve yazımları da atomiktir. Uzun, ulong, çift ve ondalık, kullanıcı tanımlı türler de dahil olmak üzere diğer türdeki okuma ve yazmaların atomik olduğu garanti edilmez.

Ancak sıkı bir döngü içinde belki Kayıt önbellekleme ile ısırıldı. Bu durumda, yöntem çağrınız belirtilmemişse (hangisi olabilir). Şahsen ben ekleyebilirim lock basit ve öngörülebilir hale getirmek için volatile burada da yardımcı olabilir. Ve tam iplik güvenliğin sadece atomiklikten daha fazlası olduğunu unutmayın.

Bir önbellek durumunda bakıyorum Interlocked.CompareExchangeşahsen - yani Deneyin güncellemek, ancak eğer çalışma başarısız olursa sıfırdan (yeni değerden başlayarak) ve tekrar deneyin.


54
2018-03-06 09:08



+1 Mükemmel, hızlı cevap için teşekkürler. Dil özelliklerine bir bağlantınız olmazdı. Çevrimiçi olarak mevcutsa? - Steffen
@Steffan, MS sürümlerini kolayca bulabileceğiniz eğilimi olan "C # Dil Özellikleri" ni arar. Veya 2.0 genel sürümü için ECMA334. - Marc Gravell♦
+1 Sadece atomikliğin ötesine geçmek için. - Albin Sunnanbo
Birisi "Kayıtlı önbelleğe alma ile ısırılmış olabilirsiniz" konusunda ayrıntılı bilgi verebilir misiniz? Bunun sonuçları ne olur? - Nathan
@Nathan basitçe: A iş parçacığı, B iş parçacığının bir değişkene yaptığı değişiklikleri mutlaka görmez. Bu özellikle gibi şeyler ile fark edilir bool shouldRun = true;, while(shouldRun) {...} ve ayarlayan ikinci bir konu shouldRun = false; - Marc Gravell♦


@Marc Gravell'in cevabında, C # Dil Spesifikasyonu 5.5'te atıfta bulunularak, "kullanıcı tanımlı tip" terimiyle kastedilenin bilinmesi önemlidir. Net bir tanımlama bulamadım. C # Dil Özelliğinde bu kullanım. UML'de ve ortak paritede, bir Sınıf bir Türün örneğidir. Ancak C # Dil Özelliği bağlamında, anlamı açık değildir.

Visual Basic Dil Başvurusu bölümü "Kullanıcı Tanımlı Tipler" (at) https://msdn.microsoft.com/en-us/library/cec05s9z.aspx) diyor

"Visual Basic'in önceki sürümlerinde kullanıcı tanımlı tür (UDT) destekleniyor. Geçerli sürüm UDT'yi bir yapıya genişletiyor."

Bu yüzden Kullanıcı tanımlı bir Tip bir Sınıf değil, bir yapıdır.

Fakat ....

"C # Programlama Rehberi" bölümüne göre "Türler" https://msdn.microsoft.com/en-us/library/ms173104.aspx):

"Tipik bir C # programı sınıf kütüphanesinden ve   kullanıcı tanımlı türler "

Sınıf anlamına gelen, kullanıcı tanımlı bir türüdür. Daha sonra, "karmaşık kullanıcı tanımlı türler" bir örnek verir:

MyClass myClass;

"MyClass", kullanıcı tanımlı bir tür anlamına gelir. Ve sonra diyor ki:

"CTS'deki her tür, bir değer türü veya referans olarak tanımlanır   yazın. Bu, .NET Framework sınıfındaki tüm özel türleri içerir.   kütüphane ve ayrıca kendi kullanıcı tanımlı tipleriniz. "

... bir geliştirici tarafından oluşturulan tüm Sınıfların "Kullanıcı Tanımlı Tip" olduğunu ima eder.

Son olarak, bu terimin anlamının tutarsız bir şekilde tartışıldığı bu Stackoverflow öğesi var: Bir özelliğin C # olarak kullanıcı tanımlı bir tür olup olmadığını nasıl belirleyebilirim?

Bu nedenle, güvenli olmak için, oluşturduğum ya da .Net Framework'de bulunan tüm Kullanıcıların, Kullanıcı Tanımlı Türler olduğu ve bu nedenle C # içinde yazdığı için ödev için Güvenli Değildir. Dil Özelliği bölüm 5.5:

Kullanıcı tanımlı türlerin yanı sıra okur ve yazarlar, atomik olma garantili değildir.

C # Dil Özellikleri gibi kesin bir şartnamede bir konuşma dilinin kullanılması talihsiz bir durumdur. Bu belirsizlik nedeniyle, iş parçacığı güvenliğini sağlamak için, "Kullanıcı tanımlı Tür" CLR Sınıflarını içermezse, mümkün olandan daha az optimal kod yazıyor olabilir.

Bu nedenle, bu yığın belirsizliği cevabının daha da açıklığa kavuşturulmasını rica ediyorum çünkü cevap için bu temel belirsizlik ortadan kalkıyor. Durduğu gibi, sorunun cevabı "Referans ataması threadafe midir?" gibi görünüyor "YOK HAYIR".


0
2018-04-24 19:56



"Kullanıcı tanımlı türler" teriminin kullanılmasındaki görünürdeki tutarsızlığa rağmen, bunun orijinal cevabı hiç sorgulamadığını düşünüyorum. İlgili bölümlerin alıntılanması: "Aşağıdaki veri türlerini okuyor ve yazıyor atomik: bool, char, ... ve referans türleri. Kullanıcı tanımlı türler de dahil olmak üzere DİĞER TİPLER" in okumaları ve yazmaları atomik olma garantili değildir. ." Benim düşünceme göre, bu durumda "öteki", başlangıç ​​listesinde (yani referans türleri) yer alan herhangi bir şeyi açıkça hariç tutmaktadır. Böylece, "kullanıcı tanımlı türler" bazen sınıfları tanımlamak için kullanılsa bile, kesinlikle burada değil. - The Mad Coder