Java Synchronized: Ensuring Thread-safety with Synchronization
Java synchronized является ключевым словом в языке программирования Java, которое позволяет контролировать параллельный доступ к общим ресурсам из нескольких потоков. Рассмотрим пример, когда несколько потоков пытаются обратиться к одному объекту, изменить его свойство и сохранить изменения.
Без синхронизации возможно ситуация, когда два потока одновременно получат значение переменной, добавят к ней свое значение и сохрнят результат в переменной. В результате, одно значение потеряется и изменения одного потока могут быть перезаписаны изменениями другого.
java
class SyncDemo {
private int counter = 0;
public void increment() {
counter++;
}
public int getValue() {
return counter;
}
}
class CounterThread extends Thread {
private SyncDemo demo;
public CounterThread(SyncDemo demo) {
this.demo = demo;
}
public void run() {
synchronized (demo) { // синхронизация
demo.increment();
System.out.println("Value = " + demo.getValue() + " :: Thread Name = " + Thread.currentThread().getName());
}
}
}
public class SynchronizationExample {
public static void main(String[] args) throws Exception {
SyncDemo syncDemo = new SyncDemo();
CounterThread[] threads = new CounterThread[5];
for (int i = 0; i < threads.length; i++) {
threads[i] = new CounterThread(syncDemo);
threads[i].setName("Thread-" + (i + 1));
threads[i].start();
}
for (int i = 0; i < threads.length; i++) {
threads[i].join();
}
}
}
Пример демонстрирует создание пяти потоков, работающих с объектом SyncDemo. Для того, чтобы одновременно только один поток мог изменить значение переменной counter используется ключевое слово synchronized.
Синхронизация выполняется на объекте, в данном случае на экземпляре класса SyncDemo, для которого доступ к ресурсам контролируется. Как только один поток получает доступ к общему ресурсу, он блокирует его для других потоков. Таким образом, другие потоки ожидают, пока предыдущий завершит свою работу и освободит общий ресурс.
Вывод программы будет следующим:
Value = 1 :: Thread Name = Thread-1
Value = 2 :: Thread Name = Thread-2
Value = 3 :: Thread Name = Thread-5
Value = 4 :: Thread Name = Thread-4
Value = 5 :: Thread Name = Thread-3
Как видно из вывода, потоки работают в порядке их запуска, каждый из них инкрементирует счетчик на единицу, и после этого сохраняет измененное значение. Синхронизация позволяет контролировать порядок выполнения потоков и избежать проблем работы в многопоточном окружении.