Топ-100Synchronized static в Java - CodOrbits
LogoCodOrbits

Раздел: Многопоточность

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

Все разделы
Иконка Многопоточность

Synchronized static в Java

Last updated: 6 мая 2025 г.

synchronized static (блокировка на уровне класса), а просто synchronized (блокировка на уровне объекта).

В коде ниже у нас уже будут 2 объекта ресурса одного класса. В них уже будет synchronized static блок.

В отличии от synchronized, блок synchronized static распространяется на все объекты одного класса.

То есть если поток дошел до synchronized static в одном объекте класса, то он блокирует этот кусок кода не только для других потоков, которые доходят до этого synchronized static в этом же объекте, а и для тех потоков, которые доходят до этого synchronized static в другом объекте того же класса, что и первый объект.

Пример программы:

1public class StaticSinchExample {
2    public static void main(String[] args) {
3        // объект ресурса номер 1
4        CommonResource commonResource1 = new CommonResource();
5        // объект ресурса номер 2
6        CommonResource commonResource2 = new CommonResource();
7        for (int i = 1; i < 6; i++) {
8            // запускаем 5 потоков, передаем в каждый из них
9            // первый ресурс, общий для 5 потоков
10            Thread t1 = new Thread(new CountThread(commonResource1));
11            // запускаем 5 потоков, передаем в каждый из них
12            // второй ресурс, общий для 5 потоков
13            Thread t2 = new Thread(new CountThread(commonResource2));
14            t1.setName("Thread t1_" + i);
15            t2.setName("Thread t2_" + i);
16            t1.start();
17            t2.start();
18        }
19        // То есть, если один из 10 запускаемых выше потоков
20        // дойдет до блока synchronized static в каком-либо
21        // из объектов ресурсов, будь то commonResource1
22        // или commonResource2, то блок synchronized static
23        // будет заблокирован для всех остальных потоков
24        // во всех объектах ресурсов.
25    }
26}
27
28class CommonResource {
29    int x;
30    static int x1;
31    
32    synchronized static void incrementstatic() {
33        // Верхнюю строчку можно было бы переписать
34        // как synchronized (CommonResource.class) –
35        // блокирует для остальных потоков блок кода
36        // класса, а не блок кода конкретного объекта.
37        x1 = 1;
38        for (int i = 1; i < 5; i++) {
39            System.out.printf("Static %s %d \n", 
40                Thread.currentThread().getName(), x1);
41            x1++;
42            try {
43                Thread.sleep(1100);
44            } catch (InterruptedException e) {}
45        }
46    }
47
48    synchronized void increment() {
49        // Верхнюю строчку можно было бы переписать
50        // как synchronized (this) – блокирует для
51        // остальных потоков блок кода
52        // конкретного объекта.
53        x = 1;
54        for (int i = 1; i < 5; i++) {
55            System.out.printf("%s %d \n", 
56                Thread.currentThread().getName(), x);
57            x++;
58            try {
59                Thread.sleep(100);
60            } catch (InterruptedException e) {}
61        }
62    }
63}
64
65class CountThread implements Runnable {
66    CommonResource res;
67    
68    CountThread(CommonResource res) {
69        this.res = res;
70    }
71    
72    public void run() {
73        CommonResource.incrementstatic();
74    }
75}

Вывод:

Как видно, все 10 потоков выводятся по очереди.

То есть 4 значения одного потока из 10 потоков, потом 4 значения другого из 10 потоков и так до десятого потока.

Что значит, что блокировка synchronized static распространяется на все объекты ресурсов.


Детали о разнице synchronized static и просто synchronized.

synchronized static (на уровне класса) и просто synchronized (на уровне объекта) это ДВЕ РАЗНЫЕ БЛОКИРОВКИ. Могут выполняться параллельно друг другу.

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

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

То есть просто syncronized метод в объекте и synchronized static метод в этом объекте могут выполняться параллельно друг другу.

Пример программы:

1public class StaticSinchExample2 {
2    public static void main(String[] args) {
3        //Объект ресурса
4        CommonResource commonResource = new CommonResource();
5        for (int i = 1; i < 6; i++) {
6            //запускаем 5 потоков и передаем
7            //в каждый из них ресурс общий для потоков
8            Thread t = new Thread(new CountThread(commonResource));
9            t.setName("Thread " + i);
10            t.start();
11        }
12    }
13}
14
15class CommonResource {
16    int x;
17    static int x1;
18
19    synchronized void increment() {
20        x = 1;
21        for (int i = 1; i < 5; i++) {
22            System.out.printf("%s %d \n", Thread.currentThread().getName(), x);
23            x++;
24            try {
25                Thread.sleep(250);
26            } catch (InterruptedException e) {}
27        }
28    }
29
30    synchronized static void incrementstatic() {
31        x1 = 1;
32        for (int i = 1; i < 5; i++) {
33            System.out.printf("Static %s %d \n", Thread.currentThread().getName(), x1);
34            x1++;
35            try {
36                Thread.sleep(700);
37            } catch (InterruptedException e) {}
38        }
39    }
40}
41
42//Код synchronized метода и synchronized static метода
43//не должны пересекаться так как блоки synchronized static
44//и просто synchronized могут выполняться параллельно,
45//а если они могут выполняться параллельно значит
46//они не синхронизированы между собой.
47
48class CountThread implements Runnable {
49    CommonResource res;
50
51    CountThread(CommonResource res) {
52        this.res = res;
53    }
54
55    public void run() {
56        //один поток может выполнять incrementstatic метод
57        CommonResource.incrementstatic();
58        //другой поток может в это же время
59        //параллельно выполнять increment
60        res.increment();
61    }
62}

Вывод:

Как видно, после выхода Thread 1 из incrementstatic метода Thread 1 входит в increment метод и выполнение этого метода, как видно, происходит параллельно потоку Thread 5, который зашел в incrementstatic метод как только из него вышел Thread 1.

То есть очевидно synchronized static блок и synchronized блок выполняются параллельно друг другу.


Следующие уроки

Синхронизация с помощью Wait/Notify

9
мин.

Similar Articles Icon
Divider

Метод yield в Java

10
мин.

Similar Articles Icon
Divider

Semaphore в Java

10
мин.

Similar Articles Icon