Есть следующая учебная программка.
В программе есть синхронизированный блок. Синхронизация работает если использовать в качестве объекта синхронизации что угодно и даже массив values
, но не работает при использовании Integer
count
.
synchronized (count) {
incrementCount();
values[getCount()]++;
}
В тоже время если объявить другой объект Integer
, то синхронизация по нему будет работать.
synchronized (other) {
incrementCount();
values[getCount()]++;
}
Почему нельзя использовать синхронизацию по count
?
public class Solution {
public static void main(String[] args) throws InterruptedException {
Counter counter1 = new Counter();
Counter counter2 = new Counter();
Counter counter3 = new Counter();
Counter counter4 = new Counter();
counter1.start();
counter2.start();
counter3.start();
counter4.start();
counter1.join();
counter2.join();
counter3.join();
counter4.join();
for (int i = 1; i <= 100; i++) {
if (values[i] != 1) {
System.out.println("Массив values содержит элементы неравные 1");
break;
}
}
}
public static Integer count = 0;
public static int[] values = new int[105];
static {
for (int i = 0; i < 105; i++) {
values[i] = 0;
}
}
public static void incrementCount() {
count++;
}
public static int getCount() {
return count;
}
public static class Counter extends Thread {
@Override
public void run() {
do {
synchronized (count) {
incrementCount();
values[getCount()]++;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
} while (getCount() < 100);
}
}
}
Объекты типа Integer
иммутабельны, операция инкремента count++
не меняет состояние объекта по ссылке, после инкремента переменная count
будет ссылаться на другой объект в куче.
Integer count = 0;
...
synchronized (count) {
incrementCount(); // тут происходит count++;
...
}
Что тут происходит:
Вы захватываете монитор (MonitorEnter
) на объекте, доступном по ссылке count
.
Вы инкрементируете значение count
, теперь count
ссылается на новый Integer
.
В секцию synchronized
может зайти другой поток, т.к. по ссылке count
объект, на котором еще не произошел MonitorEnter
.
Как-то так.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
При нажатии кнопки меню в MainActivity обновляются данные, изпользуемые в RecyclerViewСам рецайклер сидит во фрагменте, пытаюсь сообщить ему, что данные...
В примерах кода в своей книге ("Структуры данных и алгоритмы") Лафоре не пользуется методом lengthА отдельно объявляет дину массива, например...
myRad имеет тип floatКто-нибудь знает, что нужно исправить? У меня есть другие переменные float, но они не подчёркнуты