Бесплатный курс по Java: от основ до продвинутого уровня
Синхронизация в Java с помощью Synchronized
Если несколько параллельных потоков одновременно хотят выполнить один и тот же кусок кода одного и того же объекта, то можно сделать так чтобы они выполняли его поочереди.
То есть они можно сказать выстраиваются в очередь чтобы воспользоваться куском кода в объекте. Смотри пример.
Пример программы:
public class SynchronizedExample {
public static void main(String[] args) {
// Объект ресурса (общий для потоков ресурс)
CommonResource commonResource = new CommonResource();
// Запускаем 5 потоков, передавая в каждый из них
// ресурс, общий для потоков.
for (int i = 1; i < 6; i++) {
Thread t = new Thread(new CountThread(commonResource));
t.setName("Thread " + i);
t.start();
}
// Когда выполнение кода одного из параллельных
// потоков доходит до оператора synchronized,
// доступ к блоку кода synchronized объекта
// ресурса (commonResource) блокируется, и на
// время его блокировки монопольный доступ к
// блоку кода в этом объекте имеет только один
// поток, который дошел до synchronized и который
// произвел блокировку, и все прочие потоки,
// которые используют commonResource будут ждать
// пока поток, который первый дошел до блока
// synchronized, закончит его выполнение.
}
}
class CommonResource {
int x;
// Когда один из потоков доходит сюда, доступ
// к блоку кода synchronized объекта
// CommonResource блокируется, и другие потоки
// которые дошли до synchronized останавливаются
// и ждут, пока поток, дошедший сюда раньше них,
// выполнит блок synchronized. Когда он все-таки
// выполнил synchronized, в synchronized заходит
// другой поток из очереди, и другие ждут, пока уже
// этот другой поток выполнит код synchronized,
// и так далее со всеми остальными потоками
// в очереди.
synchronized void increment() {
x = 1;
for (int i = 1; i < 5; i++) {
System.out.printf("%s %d \n", Thread.currentThread().getName(), x);
x++;
try {
Thread.sleep(700);
} catch (InterruptedException e) {}
}
}
}
class CountThread implements Runnable {
CommonResource res;
CountThread(CommonResource res) {
this.res = res;
}
public void run() {
res.increment(); // вызываем синхронизированный метод
}
}
Вывод:
Благодаря этому потоки будут работать с ресурсом поочередно и от 1 до 4 сначала выведет первый дошедший до synchronized поток потом второй и так далее. Видим в консоли, что потоки выстроились в очередь в таком порядке – 1 5 2 4 3.
Разница между synchronized и synchronized static в Java. Как блокировка на уровне класса влияет на все объекты. Практические примеры и выводы.
Time to read: 15
Синхронизация с помощью Wait/Notify
Узнайте, как использовать wait/notify в Java для приостановки и возобновления потоков. Примеры кода и объяснение работы механизма межпоточной синхронизации.
Time to read: 9
Метод yield в Java
Метод yield() в Java: зачем поток уступает свое время другим? Разбор работы планировщика потоков и практическое применение с примером.