Руководство по синхронизации в Java

Опубликовано: 2022-10-23

Прежде чем мы объясним синхронизацию в Java , мы должны кратко вернуться к концепции многопоточности. Функция многопоточности Java позволяет одновременно выполнять две или более частей программы для максимального использования ЦП. Каждая часть такой программы представляет собой поток, а потоки — это легковесные процессы внутри процесса.

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

Ознакомьтесь с нашими бесплатными технологическими курсами, чтобы получить преимущество над конкурентами.

В этом руководстве о том, что такое синхронизация в Java , подробно рассматривается концепция синхронизации с примерами.

Изучайте онлайн-курсы по разработке программного обеспечения в лучших университетах мира. Участвуйте в программах Executive PG, Advanced Certificate Programs или Master Programs, чтобы ускорить свою карьеру.

Оглавление

Что такое синхронизация в Java?

Синхронизация Java — это возможность контролировать доступ нескольких потоков к общему ресурсу. Это полезно, когда многопоточные Java-программы пытаются получить доступ к одному и тому же ресурсу и дают ошибочные результаты. Используя функцию синхронизации Java, только один поток может получить доступ к ресурсу в данный момент времени.

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

Ознакомьтесь с расширенной сертификацией upGrad в области DevOps

Синтаксис записи синхронизированного блока

Общий синтаксис для записи синхронизированного блока в Java выглядит следующим образом:

синхронизированный (объект блокировки)

{

// синхронизированные операторы

}

Изучите наши популярные курсы по программной инженерии

Магистр компьютерных наук LJMU и IIITB Программа сертификатов кибербезопасности Caltech CTME
Учебный курс по полной разработке стека Программа PG в блокчейне
Программа Executive PG в Full Stack Development
Посмотреть все наши курсы ниже
Курсы по разработке программного обеспечения

В приведенном выше синтаксисе lockObject относится к объекту, блокировка которого связана с синхронизированными элементами. Теперь это подводит нас к концепции блокировки в Java.

Ознакомьтесь с расширенной сертификацией upGrad по кибербезопасности

Блокировки в Java

Синхронизация в Java построена вокруг блокировки или монитора. Каждый объект имеет связанную блокировку. В идеале поток, которому требуется доступ к полям объекта, должен сначала получить блокировку объекта. Блокировка является более сложным и гибким механизмом синхронизации потоков, чем блок синхронизации. Он определен внутри пакета java.util.concurrent.lock, содержащего расширенные реализации блокировки.

Востребованные навыки разработки программного обеспечения

Курсы JavaScript Базовые курсы Java Курсы по структурам данных
Курсы Node.js Курсы SQL Курсы разработки полного стека
Курсы НФТ Курсы DevOps Курсы по большим данным
Курсы React.js Курсы по кибербезопасности Курсы облачных вычислений
Курсы по проектированию баз данных Курсы Python Курсы по криптовалюте

Синхронизированный метод Java

Целью синхронизированного метода Java является блокировка объектов для общих ресурсов. Таким образом, когда потоки вызывают синхронизированный метод, этот метод автоматически получает блокировку для этого объекта и освобождает ее, как только поток выполняет свою работу.

Вот пример синхронизированного метода Java:

//пример синхронизированного метода Java

Таблица классов{

синхронизированный void printTable(int n){//синхронизированный метод

для (целое я = 1; я <= 5; я ++) {

Система.out.println(n*i);

пытаться{

Thread.sleep(400);

} поймать (Исключение e) {System.out.println (e);}

}

}

}

класс MyThread1 расширяет Thread{

Таблица т;

MyThread1 (Таблица т) {

это.т=т;

}

публичный недействительный запуск () {

т.printTable (5);

}

}

класс MyThread2 расширяет Thread{

Таблица т;

MyThread2 (Таблица т) {

это.т=т;

}

публичный недействительный запуск () {

т.printTable (100);

}

}

открытый класс TestSynchronization2 {

public static void main (String args []) {

Table obj = new Table();//только один объект

MyThread1 t1 = новый MyThread1 (объект);

MyThread2 t2 = новый MyThread2 (объект);

t1.старт();

t2.старт();

}

}

Прочтите наши популярные статьи, связанные с разработкой программного обеспечения

Как реализовать абстракцию данных в Java? Что такое внутренний класс в Java? Идентификаторы Java: определение, синтаксис и примеры
Понимание инкапсуляции в ООП на примерах Объяснение аргументов командной строки в C 10 основных функций и характеристик облачных вычислений в 2022 году
Полиморфизм в Java: концепции, типы, характеристики и примеры Пакеты в Java и как их использовать? Учебник по Git для начинающих: Изучайте Git с нуля

Выход:

5

10

15

20

25

100

200

300

400

500

Что происходит без синхронизации?

Теперь давайте посмотрим на предыдущую программу без синхронизации (обратите внимание на отсутствие ключевого слова synchronized).

Таблица классов{

void printTable(int n){//метод не синхронизирован

для (целое я = 1; я <= 5; я ++) {

Система.out.println(n*i);

пытаться{

Thread.sleep(400);

} поймать (Исключение e) {System.out.println (e);}

}

}

}

класс MyThread1 расширяет Thread{

Таблица т;

MyThread1 (Таблица т) {

это.т=т;

}

публичный недействительный запуск () {

т.printTable (5);

}

}

класс MyThread2 расширяет Thread{

Таблица т;

MyThread2 (Таблица т) {

это.т=т;

}

публичный недействительный запуск () {

т.printTable (100);

}

}

класс TestSynchronization1 {

public static void main (String args []) {

Table obj = new Table();//только один объект

MyThread1 t1 = новый MyThread1 (объект);

MyThread2 t2 = новый MyThread2 (объект);

t1.старт();

t2.старт();

}

}

Выход:

5

100

10

200

15

300

20

400

25

500

Как видите, без синхронизации вывод противоречив.

Типы синхронизации в Java

Чтобы ответить на вопрос , что такое синхронизация потоков в Java , у нас есть два типа синхронизации: синхронизация потоков и синхронизация процессов.

Давайте разберемся, что означает каждый.

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

Синхронизация процессов: это относится к одновременному выполнению нескольких процессов для достижения состояния, в котором процессы фиксируются в соответствующем порядке выполнения. Синхронизация процессов требуется, когда два или более процессов взаимодействуют друг с другом, и выполнение одного процесса влияет на другой. Таким образом, синхронизация процессов исключает возможность неточных выводов и гарантирует правильный порядок выполнения.

Методы синхронизации в Java

В общем, в Java есть четыре метода синхронизации:

  • Синхронизированные статические методы
  • Синхронизированные методы экземпляра
  • Синхронизированный блок внутри статических методов
  • Синхронизированный блок внутри методов экземпляра

Давайте рассмотрим каждый метод синхронизации Java более подробно.

Синхронизированные статические методы

Здесь мы используем ключевое слово synchronized для обозначения статических методов в Java. Вот пример синхронизированного статического метода Java:

общедоступный статический MyStaticCounter {

частный статический счетчик целых чисел = 0;

общественное статическое синхронизированное недействительное приращение (целое значение) {

количество += значение;

}

}

Синхронизированные методы экземпляра

При использовании синхронизированного блока с методами экземпляра каждый объект имеет свой синхронизированный метод. Каждый объект может иметь только один поток, который может выполняться внутри метода. Если имеется несколько объектов, один поток может выполняться для каждого объекта внутри блока.

открытый класс MyCounter {

частный счетчик = 0;

общественное синхронизированное недействительное приращение (целое значение) {

this.count += значение;

}

общественное синхронизированное декрементирование недействительным (целое значение) {

this.count -= значение;

}

}

Синхронизированный блок внутри статических методов

Ниже приведен пример, где мы используем синхронизированный блок внутри статического метода:

открытый класс MyClass {

public static void print (строковое сообщение) {

синхронизированный (MyClass.class) {

log.writeln(сообщение);

}

}

}

Синхронизированный блок внутри методов экземпляра

Вместо синхронизации всего метода мы можем использовать синхронизацию для определенного блока внутри метода. Ниже приведен пример синхронизированного блока кода внутри несинхронизированного метода:

общественное недействительное приращение (целое значение) {

синхронизированный (это) {

this.count += значение;

}

}

Необходимость синхронизации в Java

Теперь, когда вы знаете, что такое синхронизация в Java , вам может быть интересно, почему мы вообще ее используем.

Ключевое слово synchronized в Java предоставляет функциональные возможности, необходимые для параллельного программирования. Вот как помогает синхронизация в Java:

  • Синхронизация Java обеспечивает функцию блокировки для устранения любого состояния гонки между потоками и обеспечения взаимоисключающего доступа к общему ресурсу.
  • Синхронизированная блокировка Java обеспечивает функции как блокировки, так и разблокировки. Таким образом, поток должен получить блокировку перед входом в синхронизированный метод или блок.
  • Синхронизированное ключевое слово предотвращает изменение порядка операторов программы компилятором.

Вывод

Подводя итог, синхронизация в Java гарантирует, что только один поток может получить доступ к общему ресурсу в любой момент времени. Мы можем сделать блок или метод синхронизированным, используя ключевое слово synchronized в Java. Когда поток хочет попасть внутрь синхронизированного блока, он должен получить блокировку, а после выхода из блока поток снимает блокировку. Мы можем использовать ключевое слово synchronized либо с методами, либо внутри блока метода.

Хотите изучить основные концепции Java? Программа upGrad Executive Post Graduate Program в области разработки программного обеспечения — курс «Специализация в разработке полного стека» — это 7-недельная онлайн-программа для начинающих, которые хотят изучить карьеру в области разработки программного обеспечения. Посещайте живые и интерактивные занятия, практические занятия и более 35 часов контента от лидеров отрасли, чтобы получить сертификат об окончании от upGrad.

Зарегистрируйтесь сегодня , чтобы воспользоваться эксклюзивными преимуществами upGrad в виде круглосуточной поддержки студентов и отраслевых сетей!

Почему мы используем синхронизацию в Java?

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

Как реализована синхронизация в Java?

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

Что такое взаимоблокировка в Java?

Взаимная блокировка Java возникает, когда поток ожидает блокировки объекта, но другой поток получает ее, а второй поток ожидает блокировки объекта, полученной первым. Следовательно, оба потока ждут друг друга, чтобы снять блокировку, что приводит к взаимоблокировке.