2013-05-01 20 views
7

Wiem, że w java, jeśli masz wiele wątków uzyskujących dostęp do zmiennej, która nie jest oznaczona jako niestabilna, możesz uzyskać nieoczekiwane zachowanie.Czy zmienne słowo kluczowe C# i java zachowuje się w taki sam sposób?

Przykład:

private boolean bExit; 

while(!bExit) { 
    checkUserPosition(); 
    updateUserPosition(); 
} 

Jeśli zaznaczysz zmienną bExit jako voilatile, że gaurantee że inne wątki ujrzy najnowsza wartość.

Czy C# zachowuje się tak samo?

Aktualizacja

Na przykład w C# jeśli to zrobić:

int counter = ...; 

for(...) 
{ 
    new Thread(delegate() 
    { 

     Interlocked.Decrement(ref counter); 
    } 
} 


if(counter == 0) 
{ 
    // halt program 
} 

W powyższym przykładzie, w C# zrobić trzeba zaznaczyć zmienną licznika jako lotny lub to będzie działać zgodnie z oczekiwaniami?

+1

Każdy * model pamięci * (modele pamięci JVM lub CLR) ma inny zestaw reguł z pewnym nakładaniem się. Rozważ szukanie poprawnych (i niepoprawnych) zastosowań 'volatile' w obu językach/wersjach językowych i porównawczych. – user2246674

+0

Loteria C# jest naprawdę zarezerwowana do użycia w aplikacjach o niskiej pamięci i powinna być używana tylko jako absolutna ostatnia deska ratunku. Jest tam pewna dokumentacja, którą warto przyjrzeć pod kątem C#: http://msdn.microsoft.com/en-us /library/x13ttww7(v=vs.71).aspx – Nomad101

+1

@ Nomad101 - Nie jestem pewien, jaki jest związek między aplikacjami o niskiej pamięci a zmiennym słowem kluczowym. – hatchet

Odpowiedz

0

Jeśli zaznaczysz zmienną bExit jako voilatile, że gaurantee że inne wątki ujrzy najnowsza wartość. Czy C# zachowuje się w ten sam sposób?


Tak, ale wszystko zależy od tego, jak masz dostęp do zmiennej współdzielonej. jako twój przykład, jeśli uzyskasz dostęp do zmiennego w sposób bezpieczny dla wątków, taki jak Interlocked.Decrement, nie będzie to problemem, nawet bez użycia voilatile.

volatile (C# Reference from MSDN)

Lotny parametru wskazuje, że pola może być modyfikowany przez wielu wątków, które realizują w tym samym czasie. Pola oznaczone jako deklarowane jako "lotne" nie podlegają optymalizacji kompilatora, które zakładają, że dostęp jest możliwy przez pojedynczy wątek. Zapewnia to, że najbardziej aktualna wartość jest obecna w polu przez cały czas.

What is the "volatile" keyword used for?

+0

Więc mam rację, rozumiejąc, że bez lotności, możesz uzyskać nieoczekiwane wyniki podczas odczytywania nielotnej zmiennej, która jest aktualizowanie moich wielu wątków? – loyalflow

+1

Czytałem, że lotny nie robi właściwie tego, co wielu ludzi uważa. Polecam lekturę http://www.albahari.com/threading/part4.aspx#_The_volatile_keyword – hatchet

0

Trzeba być nieco ostrożnym tutaj jako wybraniu dwóch różnych typów w swoich przykładach. Moja ogólna zasada jest taka, że ​​lotność najlepiej jest stosować w przypadku booleans i ze wszystkim innym prawdopodobnie potrzebujesz innego mechanizmu synchronizacji. W języku C# i java bardzo często używa się zmiennej wartości boolowskiej np. zatrzymać pętlę lub zadania wykonującego, który ma widoczność z wielu wątków:

class Processor 
{ 
    private volatile Boolean _stopProcessing = false; 

    public void process() 
    { 
     do 
     { ... } 
     while (!_stopProcessing); 
    } 

    public void cancel() 
    { 
     _stopProcessing = true; 
    } 
} 

Powyższy będzie pracować w języku C# lub Java i w tym przykładzie lotny słów kluczowych oznacza, że ​​odczyt w metodzie procesowej będzie od rzeczywistej wartości prądu a nie wartości buforowanej. Kompilator lub maszyna wirtualna może w inny sposób zezwolić na buforowanie wartości, ponieważ pętla w procesie nie zmienia samego _stopProcessing.

Odpowiedź jest więc twierdząca na pierwsze pytanie.

Chociaż można użyć parametru volatile na int, pomaga to tylko wtedy, gdy czytasz tylko jedną literę lub piszesz jedną wartość. Jak tylko zrobisz coś bardziej złożonego, np.inkrementacji, potrzebujesz innego rodzaju synchronizacji, na przykład korzystania z opcji Interlocked. W drugim przykładzie wciąż jednak czytasz wartość licznika bez żadnej synchronizacji, więc skutecznie polegasz na innych zastosowaniach licznika, które mają być zsynchronizowane (np. Z zablokowanymi).

W swoim drugim przykładzie nadal lepiej byłoby oznaczać, że twój int jest niestabilny, w ten sposób ponownie możesz mieć pewność, że otrzymujesz aktualną wartość, a nie jakąś wersję buforowaną. Jednak używanie samego lotnego nie jest wystarczające, ponieważ odczyt na dole może pokrywać się ze standardowym spadkiem (licznik), a nie z poprawnym użyciem sprzężonych.

Powiązane problemy