To jest pytanie szczegółowe dla C#.C# bezpieczeństwo wątków z get/set
Załóżmy Mam klasy z obiektu, a obiekt jest chroniony przez śluzy:
Object mLock = new Object();
MyObject property;
public MyObject MyProperty {
get {
return property;
}
set {
property = value;
}
}
Chcę wątek odpytywania, aby móc kwerendy tę właściwość. Chcę również, aby wątek aktualizował właściwości tego obiektu sporadycznie, a czasami użytkownik może zaktualizować tę właściwość, a użytkownik chce mieć możliwość zobaczenia tej właściwości.
Czy poniższy kod poprawnie zablokuje dane?
Object mLock = new Object();
MyObject property;
public MyObject MyProperty {
get {
lock (mLock){
return property;
}
}
set {
lock (mLock){
property = value;
}
}
}
Przez „właściwie”, co mam na myśli to, że jeśli chcę zadzwonić
MyProperty.Field1 = 2;
czy coś, będzie pole zostać zablokowany podczas zrobić aktualizację? Czy ustawienie jest wykonywane przez operatora equals w zakresie funkcji get, czy też funkcja "get" (a więc blokada) zostanie zakończona jako pierwsza, a następnie ustawienie, a następnie "set" zostanie wywołane, a więc obejście zamek?
Edycja: Ponieważ to najwyraźniej nie wystarczy, co będzie? Czy muszę zrobić coś takiego:
Object mLock = new Object();
MyObject property;
public MyObject MyProperty {
get {
MyObject tmp = null;
lock (mLock){
tmp = property.Clone();
}
return tmp;
}
set {
lock (mLock){
property = value;
}
}
}
które bardziej lub mniej tylko upewnia się, że mam dostęp do kopii tylko, co oznacza, że jeśli miałbym mieć dwa wątki nazwać „get” w tym samym czasie, każdy z nich zaczynałby od tej samej wartości pola 1 (prawda?). Czy istnieje sposób, aby wykonać blokowanie odczytu i zapisu dla właściwości, która ma sens? Czy powinienem po prostu ograniczyć się do blokowania sekcji funkcji, a nie samych danych?
Tak, aby ten przykład miał sens: MyObject to sterownik urządzenia, który zwraca stan asynchronicznie. Wysyłam komendy za pośrednictwem portu szeregowego, a następnie urządzenie odpowiada na te polecenia we własnym słodkim czasie. W tej chwili mam wątek, który wypytuje go o jego status ("Czy nadal tam jesteś? Czy potrafisz przyjmować polecenia?"), Wątek oczekujący odpowiedzi na porcie szeregowym ("Otrzymałem status 2, wszystko jest w porządku"), a następnie wątek interfejsu użytkownika, który przyjmuje inne polecenia ("Użytkownik chce, abyś to zrobił.") i publikuje odpowiedzi ze sterownika ("Właśnie to zrobiłem, teraz zaktualizuj ten interfejs"). Właśnie dlatego chcę zablokować obiekt, a nie pola obiektu; to byłaby ogromna liczba zamków, a, i b, nie każde urządzenie tej klasy ma takie samo zachowanie, tylko ogólne zachowanie, więc musiałbym zakodować wiele pojedynczych okien dialogowych, jeśli zindywidualizowałem zamki.
Uzgodnione. Dostarczyłem przykładowe rozwiązanie dla tego, o co pytasz w odpowiedzi na pytanie Singletona http://stackoverflow.com/questions/7095/is-the-c-static-constructor-thread-safe/7105#7105 – Zooba
tak, ja " Prawdopodobnie pójdę z blokowaniem obiektu, tak jak to opisałeś. Dzięki. – mmr
Dobrze, gdyby jednak miał 'MyProperty' nazwany' p' i wywołał dwa wątki jednocześnie: 'p = new MyObject (12)' i 'p = new MyObject (5)' następnie * ten * dostęp byłby zsynchronizowany . Jednak członek 'Field1' nigdy * nie zostanie zablokowany. Jestem prawie pewien, że właśnie to mówisz, próbując zrozumieć to dla siebie. – Snoopy