Далее на странице
Synchronized в Java — это ключевое слово для обеспечения контроля доступа к общим ресурсам в многопоточной среде. Оно гарантирует, что в данный момент времени только один поток имеет доступ к блоку кода или методу, помеченному как synchronized.
Если поток начинает выполнять синхронизированный метод или блок кода, он получает «замок» на этот ресурс, и другие потоки не могут его использовать, пока первый поток не освободит замок.
Методы или блоки кода, которые изменяют общие данные, должны быть объявлены как synchronized, чтобы предотвратить одновременный доступ к общим ресурсам от разных потоков.
Также ключевое слово synchronized обеспечивает атомарность операций и предотвращает конфликты между потоками.
Синхронизация
Синхронизация в Java — это процесс, который позволяет только одному потоку в определённый момент времени полностью выполнить заданную задачу.
Синхронизация помогает предотвратить одновременный доступ к общим ресурсам от разных потоков и обеспечить целостность данных
Синхронизация метода
Чтобы синхронизировать метод в Java, нужно дописать «synchronized» перед названием метода.
Если в сигнатуре метода в Java указано ключевое слово synchronized, то метод использует встроенную блокировку.
При этом синхронизируется весь метод или класс.
Java-код
public synchronized void myMethod() {
System.out.println("Hi I'm synchronized method!");
}
Java-код
Синхорнизация всего метода
public synchronized void method (int index, String string) {
}
Равносильна записи
public void method (int index, String string) {
synchronized(this) {
}
}
Синхронизация блока кода
При создании синхронизированного блока кода после оператора synchronized идёт объект-заглушка.
В качестве объекта может использоваться только объект какого-нибудь класса, но не примитивного типа.
Когда выполнение кода доходит до оператора synchronized, монитор объекта блокируется, и на время его блокировки монопольный доступ к блоку кода имеет только один поток, который и произвёл блокировку. После окончания работы блока кода монитор освобождается и становится доступным для других потоков.
Java-код
public class Main {
private Object obj = new Object();
public void doSomething() {
// ...какая-то логика, доступная для всех потоков
synchronized (obj) {
// логика, которая одновременно доступна только для одного потока
}
}
}
Мьютекс и Монитор
Мьютекс — поле для синхронизации потоков. Есть у каждого объекта в Java. Неважно, какими классами пользоваться стандартными или собственными: у всех объектов всех классов есть мьютекс.
Это простейший Семафор, который может находиться в одном из двух состояний: true или false.
Монитор — это дополнительная надстройка над Мьютексом.
Блокирует объект именно монитор. Компилятор преобразует слово synchronized в несколько фрагментов кода - «под капотом» программы работает другой КОД.
Монитор в Java выражен с помощью слова synchronized. Реально работающий код, невидимый для программиста - это и есть Монитор.
Когда один тред (поток) заходит внутрь synchronized блока кода, JVM тут же блокирует Mьютекс синхронизированного объекта.
Mutex — это «флажок», переходящий к потоку, который в данный момент имеет право работать с общими ресурсами. Он исключает доступ остальных потоков к занятому участку памяти. Мьютексов в приложении может быть несколько, и они могут разделяться между процессами.
Java-код
public class Main {
private Object obj = new Object();
public void doSomething() {
//...какая-то логика, доступная для всех потоков
synchronized (obj) {
//логика, которая одновременно доступна только для одного потока
}
}
}
В блоке кода, который помечен словом synchronized, происходит захват мьютекса объекта obj.
Семафор
Семафоры представляют еще одно средство синхронизации для доступа к ресурсу. В Java семафоры представлены классом Semaphore, который располагается в пакете java.util.concurrent. Для управления доступом к ресурсу семафор использует счетчик, представляющий количество разрешений. Если значение счетчика больше нуля, то поток получает доступ к ресурсу, при этом счетчик уменьшается на единицу.
Синхронизация в статических методах. Синхронизация по классу
Пример синхронизации статических методов.
Java-код
class MyClass {
static int count;
public static synchronized int getCount() {
return count;
}
}
У каждого объекта есть мьютекс. В примере не понятно, что будет выполнять роль мьютекса.
Ведь для вызова статического метода MyClass.getCount() - не нужны объекты.
Если требуется синхронизация в статических методах, то она осуществляется по классу.
Java-код
class MyClass {
static int count;
public static int getCount() {
synchronized (MyClass.class) {
return count;
}
}
}
Каждый загруженный в Java класс имеет соответствующий объект класса Class, представляющий этот класс. Монитор именно этого объекта используется для синхронизации статических методов.
При применении статических синхронизированных методов в Java происходит блокировка всего класса. Это означает, что только один поток может выполнять этот метод класса в одно и то же время.
Дополнительно. Объект МОНИТОР
В Java монитором может быть любой объект
Объект МОНИТОР - может быть взят как из вне, например вот так:
public final Object monitor = new Object()
Так и быть полем текущего класса. Монитор - это любой объект, любого типа.
Смысл объекта МОНИТОРА и ЕГО ЗАДАЧА -
.Может ли поток блокировать мьютекс двух объектов?
Да, поток может блокировать мьютекс двух объектов.
Однако при таком подходе существует риск взаимоблокировки deadlock.
Чтобы её избежать, во всех потоках . мьютексы следует блокировать и освобождать в одном и том же порядке.
P.S.
Добрый день. Я изучаю JAVA. Некоторые темы мне довольно сложно освоить и усвоить. Поэтому я пишу такие вот статья с примерами. Делаю я это в большей степени для себя. Так мне проще понять и запомнить. Если кому-то пригодится – буду рад.
Этот материал используется исключительно в учебных целях и никакой коммерческой выгоды не несет. Текст частично взят из нейросети Яндекса, частично написан мною – материал берется из разных источников. Код писал сам, но за основу опять же брал какие-то уже существующие данные.
Если я где-то ошибся, что-то не правильно/не так описал – это нормально. Во-первых, я учусь, во-вторых, ни на что не претендую. Просьба это понимать.