• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Volatile vs Synchronized

VPS Starter Arubacloud
+4 głosów
4,590 wizyt
pytanie zadane 25 czerwca 2015 w Java przez Jaskrowicz Obywatel (1,210 p.)

Czy mógłby ktoś mi jeszcze bardziej rozjaśnić różnice między volatile a Synchronized? W uproszczeniu rozumiem, że Volatile wymusza na wątku thread sprawdzanie zgodności jego wersji (kopii) zmiennej z oryginałem czyli powoduje, że wątek (który będzie używał tej zmiennej) będzie rozpatrywał zmiany zmiennej gdyby w inny wątek go zmieniał, zaś Synchronized (użyte na metodzie), blokuje dostęp innym metodom z tego samego obiektu do działania na wspólnych zmiennych.


public class App {

	
	
	public static void main(String[] args) throws InterruptedException {
		
		final Runner runner = new Runner();
		
		Thread t1 = new Thread(new Runnable() {
			public void run() {
				try {
					runner.firstThread();;
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
			
		});
		
		Thread t2 = new Thread(new Runnable() {
			public void run() {
				try {
					runner.secondThread();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}	
			}
		});

		t1.start();
		t2.start();
		
		t1.join();
		t2.join();
		
		runner.finished();
		
	}
	

}

public class Runner {
	
	private int count = 0;
	
	private void zwiekszaj(){
		for(int i=0; i<10000; i++)
			count++;
	}
	
	public synchronized void firstThread() throws InterruptedException {
	
		zwiekszaj();
	}
	
	public synchronized void secondThread() throws InterruptedException {
		
		zwiekszaj();
	}
	
	public void finished() {
		
		System.out.println("Count wynosi: " + count);
	}

}

Przykładowo na powyższym kodzie, aby działał poprawnie dodałem synchronized przed metodami firstThread() i secondThread() [Klasa Runner], zaś dodanie volatile przed zmienną count [Klasa Runner] nie daje 100% skuteczności (choć wydaje mi się że zwiększa w pewien sposób częstotliwość pojawiania się prawidłowego wyniku).

1 odpowiedź

+1 głos
odpowiedź 7 lipca 2015 przez nowyfolder Mądrala (7,250 p.)
wybrane 11 lipca 2015 przez Jaskrowicz
 
Najlepsza

Mam troszkę czasu i przeglądam stare pytania... Także tego :P 

Czy mógłby ktoś mi jeszcze bardziej rozjaśnić różnice między volatile a Synchronized? W uproszczeniu rozumiem, że Volatile wymusza na wątku thread sprawdzanie zgodności jego wersji (kopii) zmiennej z oryginałem czyli powoduje, że wątek (który będzie używał tej zmiennej) będzie rozpatrywał zmiany zmiennej gdyby w inny wątek go zmieniał, zaś Synchronized (użyte na metodzie), blokuje dostęp innym metodom z tego samego obiektu do działania na wspólnych zmiennych.

Właściwie to sam sobie odpowiedziałeś, ale postaram się coś dodać.

Modyfikator volatile sprawia że każdy wątek który posługuje się tą zmienną ma przy niej napisane ostrzeżenie - "Uważaj - bo może ona zmienić wartość nawet wtedy, gdy się nie spodziewasz!" Wątek ten może spać przez 3 milisekundy, a w tym czasie nagle zmienna ta może zmienić wartość. Jeśli jednak ta zmienna będzie oznaczana jako Volatile, to tego wątku to nie zaskoczy, gdyż zawsze będzie on "podejrzliwy" i sprawdzał, co znajduje się pod jej adresm w pamięci. Przychodzi mi do głowy na przykład takie zastosowanie, jak nadanie tego modyfikatora do zmiennej sterującej jakąś pętlą, zmiennej, która jest zmieniana w innym wątku.

Blok kodu oznaczony jako synchronized nie może być wykonywany współbieżnie. Jesli jeden wątek zacznie wykonywać kod z bloku synchronized, to dopóki nie wyjdzie z tego bloku, inne wątki chcące wykonać ten blok będą musiały zaczekać. Pozwala to na rozwiązanie problemu sekcji krytycznej - na "atomowy" dostęp do tego bloku przez n wątków.

Jak widać obydwa rozwiązania służą do czego innego. Modyfikator volatile zapewnia nas że uzywamy najnowszej wartości zmiennej. I tylko tyle. Zmienna ta może być jednocześnie sprawdzana w instrukcji warunkowej oraz modyfikowana. Mogą istnieć 3 wątki, jednocześnie próbujące przypisać jej inną wartość. Natomiast użycie bloku synchronized pozwala na znacznie więcej.
Mam nadzieję, że coś to rozjaśni :P

komentarz 9 lipca 2015 przez Jaskrowicz Obywatel (1,210 p.)
Dzięki za odpowiedź! Jesteś jeszcze w stanie powiedzieć czemu na powyższym kodzie nie zadziała Volatile na zmienną count (po usunięciu synchronized z First- i Second- Thread)? Bo jeśli jest "podejrzliwy" i sprawdza, co znajduje się pod jej adresem w pamięci to w teorii to powinno zadziałać, a nie działa... :/
komentarz 10 lipca 2015 przez nowyfolder Mądrala (7,250 p.)

Tu właśnie napotykamy problem sekcji krytycznej. I volatile nie ma tu nic do rzeczy, ten modyfikator pozwala na widzenie najnowszej wartości zmiennej i tak się dzieje. Nie zmienia to faktu, że gdy dwa wątki wykonują count++ w tym samym momencie, to przykladowo zmienna mająca wartość 20, może mieć potem wartość 20, 21, 22, albo nawet zupełnie inną(szczerze mówiąc nie wiem czy jest to gdzieś zdefiniowane) - bo czy z volatile czy bez, nadal dochodzi do modyfikacji zmiennej w sposób współbieżny. Wniosek? Należy unikać współbieżnego operowania na zmiennych bez odpowiednich zabezpieczeń, takich jak np. bloki synchronized
Volatile jest tylko formą przypomnienia dla kompilatora, żeby nie stosował żadnych optymalizacji i zawsze starał się mieć najnowszą wartość tej zmiennej.

komentarz 11 lipca 2015 przez Jaskrowicz Obywatel (1,210 p.)

Ano tak, że na to nie wpadłem... Dzięki wielkie wink!

Podobne pytania

0 głosów
0 odpowiedzi 109 wizyt
0 głosów
1 odpowiedź 184 wizyt
pytanie zadane 25 kwietnia 2017 w C i C++ przez Daniel Janus Nowicjusz (150 p.)
0 głosów
1 odpowiedź 227 wizyt
pytanie zadane 13 lipca 2015 w C i C++ przez Pascal Bywalec (2,720 p.)

93,023 zapytań

141,986 odpowiedzi

321,290 komentarzy

62,370 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Wprowadzenie do ITsec, tom 2

Można już zamawiać tom 2 książki "Wprowadzenie do bezpieczeństwa IT" - będzie to około 650 stron wiedzy o ITsec (17 rozdziałów, 14 autorów, kolorowy druk).

Planowana premiera: 30.09.2024, zaś planowana wysyłka nastąpi w drugim tygodniu października 2024.

Warto preorderować, tym bardziej, iż mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy dodatkowe 15% zniżki! Dziękujemy zaprzyjaźnionej ekipie Sekuraka za kod dla naszej Społeczności!

...