Synchronizacja w Java – blok synchronizowany a metoda synchronizowana

Synchronizacja w Java jest mechanizmem, który zapobiega jednoczesnemu dostępowi wielu wątków do tego samego zasobu, co jest kluczowe w kontekście programowania wielowątkowego. Java oferuje dwa główne sposoby synchronizacji: przez metody synchronizowane i bloki synchronizowane. Oba te mechanizmy pomagają uniknąć problemów związanych z równoczesnym dostępem, takich jak warunki wyścigu, ale różnią się sposobem użycia i zakresem działania.

Blok synchronizowany vs metoda synchronizowana

  • Metoda synchronizowana oznacza, że cała metoda jest synchronizowana. Kiedy wątek wchodzi do metody synchronizowanej, automatycznie blokuje on obiekt, dla którego ta metoda została wywołana (lub klasę, jeśli metoda jest statyczna), uniemożliwiając innym wątkom wywołanie jakiejkolwiek z synchronizowanych metod tego obiektu lub klasy.
  • Blok synchronizowany pozwala na synchronizację wybranych instrukcji wewnątrz metody, co daje większą elastyczność. Można określić obiekt, który ma być zablokowany, co pozwala na dokładniejsze sterowanie dostępem wątków.

Przykład użycia bloku synchronizowanego

Załóżmy, że tworzymy aplikację, która symuluje działanie banku, gdzie wielu użytkowników (wątków) może jednocześnie wykonywać operacje na wspólnym koncie bankowym. Chcemy zapewnić, że operacje na koncie są wykonywane w sposób synchronizowany, aby uniknąć nieprawidłowości w saldzie.

Klasa Account
public class Account {
    private int balance = 100; // Początkowe saldo

    public void deposit(int amount) {
        // Blok synchronizowany
        synchronized (this) {
            balance += amount; // Dodanie kwoty do salda
        }
    }

    public void withdraw(int amount) {
        // Blok synchronizowany
        synchronized (this) {
            balance -= amount; // Odejmowanie kwoty od salda
        }
    }

    public int getBalance() {
        return balance; // Zwrócenie aktualnego salda
    }
}
Klasa AccountUser

Reprezentuje użytkownika (wątek) wykonującego operacje na koncie.

public class AccountUser extends Thread {
    private Account account;

    public AccountUser(Account account) {
        this.account = account;
    }

    public void run() {
        // Wykonanie operacji na koncie
        account.deposit(50);
        account.withdraw(30);
    }
}
Klasa Main

Demonstruje uruchomienie wielu wątków operujących na tym samym obiekcie Account.

public class Main {
    public static void main(String[] args) {
        Account sharedAccount = new Account();

        // Tworzenie wątków użytkowników konta
        AccountUser user1 = new AccountUser(sharedAccount);
        AccountUser user2 = new AccountUser(sharedAccount);

        user1.start(); // Uruchomienie wątku user1
        user2.start(); // Uruchomienie wątku user2
    }
}

Podsumowanie

Synchronizacja w Java jest niezbędna do bezpiecznego zarządzania dostępem do współdzielonych zasobów w aplikacjach wielowątkowych. Bloki synchronizowane oferują większą elastyczność niż metody synchronizowane, pozwalając na precyzyjne określenie zakresu kodu podlegającego synchronizacji. Przykład z kontem bankowym ilustruje, jak synchronizacja może zapewnić spójność danych w obliczu równoczesnych operacji wykonywanych przez wiele wątków.

 

Scroll to Top