Logo

Developer learning path

Java

Синхронизация потоков в Java

Синхронизация потоков

94

#example

Конкурентное использование ресурсов в многопоточных приложениях может приводить к ошибкам, таким как гонки данных (race condition) и дедлоки (deadlock). Для того чтобы избежать этих ошибок, в Java существуют механизмы синхронизации потоков.

  1. Синхронизация метода
                    
class Counter {
    private int count;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}
                  

В этом примере, методы increment и getCount синхронизированы, чтобы избежать гонки данных при многопоточном использовании объекта Counter.

  1. Использование блока синхронизации
                    
class Counter {
    private int count;

    public void increment() {
        synchronized(this) {
            count++;
        }
    }

    public int getCount() {
        synchronized(this) {
            return count;
        }
    }
}
                  

Здесь методы increment и getCount не синхронизированы, но блоки кода в них синхронизированы по объекту this.

  1. Использование Lock-объекта
                    
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Counter {
    private int count;
    private Lock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

    public int getCount() {
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }
}
                  

Этот пример использует объект Lock для синхронизации блоков кода. Метод increment блокирует lock, затем выполнение кода, затем разблокирует lock. Аналогично для метода getCount.

  1. Использование synchronized блока на статическом методе
                    
class Counter {
    private static int count;

    public static synchronized void increment() {
        count++;
    }

    public static synchronized int getCount() {
        return count;
    }
}
                  

Здесь методы increment и getCount синхронизированы с помощью synchronized на статическом методе класса Counter. Это гарантирует, что только один поток будет иметь доступ к этим методам одновременно.

  1. Использование Semaphore
                    
import java.util.concurrent.Semaphore;

class Counter {
    private int count;
    private Semaphore semaphore = new Semaphore(1);

    public void increment() throws InterruptedException {
        semaphore.acquire();
        try {
            count++;
        } finally {
            semaphore.release();
        }
    }

    public int getCount() throws InterruptedException {
        semaphore.acquire();
        try {
            return count;
        } finally {
            semaphore.release();
        }
    }
}
                  

В этом примере используется Semaphore для ограничения доступа к методам increment и getCount только одному потоку одновременно. Semaphore инициализируется значением 1, что позволяет одному потоку захватывать семафор, в то время как остальные будут ждать. Когда поток освобождает семафор, следующий поток может захватить его и так далее.

Если вам не совсем понятен какой-то абзац текста из лекции, просто нажмите на него и сможете задать уточняющие вопросы по нему.

Если же непонятен весь вопрос, то нажмите на кнопки внизу, чтобы получить новый вариант объяснения, практические примеры или критически оценить сам вопрос.