Вопрос-ответ

What does 'synchronized' mean?

Что означает "синхронизированный"?

У меня есть несколько вопросов, касающихся использования и значения synchronized ключевого слова.


  • Каково значение synchronized ключевого слова?

  • Когда должны использоваться методы synchronized?

  • Что это означает программно и логически?

Переведено автоматически
Ответ 1

Ключевое слово synchronized относится к разным потокам, считывающим и записывающим данные в одни и те же переменные, объекты и ресурсы. Это нетривиальная тема в Java, но вот цитата из Sun:


synchronized методы позволяют реализовать простую стратегию предотвращения помех потокам и ошибок согласованности памяти: если объект виден более чем одному потоку, все операции чтения или записи в переменные этого объекта выполняются с помощью синхронизированных методов.


В очень, очень краткой форме: когда у вас есть два потока, которые читают и записывают в один и тот же "ресурс", скажем, переменную с именем foo, вам нужно убедиться, что эти потоки обращаются к переменной атомарным способом. Без synchronized ключевого слова ваш поток 1 может не увидеть изменения, внесенные потоком 2 в foo, или, что еще хуже, они могут быть изменены только наполовину. Это было бы не то, чего вы логически ожидаете.

Опять же, это нетривиальная тема в Java. Чтобы узнать больше, изучите темы здесь, на SO, и в Интернете о:

Продолжайте изучать эти темы, пока имя "Брайан Гетц" не станет навсегда ассоциироваться в вашем сознании с термином "параллелизм".

Ответ 2

Что ж, я думаю, у нас было достаточно теоретических объяснений, поэтому рассмотрим этот код

public class TestThread extends Thread {
String name;
TheDemo theDemo;

public TestThread(String name, TheDemo theDemo) {
this.theDemo = theDemo;
this.name = name;
start();
}

@Override
public void run() {
theDemo.test(name);
}

public static class TheDemo {
public synchronized void test(String name) {
for (int i = 0; i < 10; i++) {
System.out.println(name + " :: " + i);
try {
Thread.sleep(500);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}

public static void main(String[] args) {
TheDemo theDemo = new TheDemo();
new TestThread("THREAD 1", theDemo);
new TestThread("THREAD 2", theDemo);
new TestThread("THREAD 3", theDemo);
}
}

Примечание: synchronized блокирует вызов метода test() следующим потоком до тех пор, пока выполнение предыдущего потока не будет завершено. Потоки могут обращаться к этому методу по одному за раз. Без synchronized все потоки могут обращаться к этому методу одновременно.

Когда поток вызывает синхронизированный метод 'test' объекта (здесь объект является экземпляром класса 'TheDemo'), он получает блокировку этого объекта, любой новый поток не может вызвать КАКОЙ-ЛИБО синхронизированный метод того же объекта до тех пор, пока предыдущий поток, получивший блокировку, не снимет блокировку.

Аналогичная вещь происходит при вызове любого статического синхронизированного метода класса. Поток получает блокировку, связанную с классом (в этом случае любой нестатический синхронизированный метод экземпляра этого класса может быть вызван любым потоком, поскольку эта блокировка на уровне объекта все еще доступна). Любой другой поток не сможет вызвать какой-либо статический синхронизированный метод класса до тех пор, пока блокировка на уровне класса не будет снята потоком, который в данный момент удерживает блокировку.

Вывод с синхронизированным

THREAD 1 :: 0
THREAD 1 :: 1
THREAD 1 :: 2
THREAD 1 :: 3
THREAD 1 :: 4
THREAD 1 :: 5
THREAD 1 :: 6
THREAD 1 :: 7
THREAD 1 :: 8
THREAD 1 :: 9
THREAD 3 :: 0
THREAD 3 :: 1
THREAD 3 :: 2
THREAD 3 :: 3
THREAD 3 :: 4
THREAD 3 :: 5
THREAD 3 :: 6
THREAD 3 :: 7
THREAD 3 :: 8
THREAD 3 :: 9
THREAD 2 :: 0
THREAD 2 :: 1
THREAD 2 :: 2
THREAD 2 :: 3
THREAD 2 :: 4
THREAD 2 :: 5
THREAD 2 :: 6
THREAD 2 :: 7
THREAD 2 :: 8
THREAD 2 :: 9

Вывод без синхронизации

THREAD 1 :: 0
THREAD 2 :: 0
THREAD 3 :: 0
THREAD 1 :: 1
THREAD 2 :: 1
THREAD 3 :: 1
THREAD 1 :: 2
THREAD 2 :: 2
THREAD 3 :: 2
THREAD 1 :: 3
THREAD 2 :: 3
THREAD 3 :: 3
THREAD 1 :: 4
THREAD 2 :: 4
THREAD 3 :: 4
THREAD 1 :: 5
THREAD 2 :: 5
THREAD 3 :: 5
THREAD 1 :: 6
THREAD 2 :: 6
THREAD 3 :: 6
THREAD 1 :: 7
THREAD 2 :: 7
THREAD 3 :: 7
THREAD 1 :: 8
THREAD 2 :: 8
THREAD 3 :: 8
THREAD 1 :: 9
THREAD 2 :: 9
THREAD 3 :: 9
Ответ 3

Ключевое слово synchronized предотвращает одновременный доступ к блоку кода или объекту несколькими потоками. Все методы Hashtable являются synchronized, поэтому только один поток может выполнять любой из них одновременно.

При использовании не-synchronized конструкций, подобных HashMap, вы должны встроить в свой код функции потокобезопасности, чтобы предотвратить ошибки согласованности.

Ответ 4

synchronized означает, что в многопоточной среде объект, имеющий synchronized метод (ы) / блок (ы), не позволяет двум потокам обращаться к synchronized методу (ам) / блоку (ам) кода одновременно. Это означает, что один поток не может читать, пока другой поток обновляет его.

Вместо этого второй поток будет ждать, пока первый поток завершит свое выполнение. Накладными расходами являются скорость, но преимуществом является гарантированная согласованность данных.

Однако, если ваше приложение однопоточное, synchronized blocks не дает преимуществ.

java multithreading