tgoop.com/dev_easy_notes/35
Last Update:
Новый пост, новая проблема, сегодня поговорим о Reordering. 👩🏫 Начнем с определения: в многопоточной среде результаты операций, произведённых другими потоками, могут наблюдаться не в том порядке, в котором мы ожидаем. Лааадно, вы же не думали, что я тут буду душнить. 🙌 Как всегда, разберем на пальцах пример:
var x = 0
var y = 1
thread {
var a = x
y = 0
print(a)
}
thread {
var b = y
x = 1
print(b)
}
Этот код может показаться немного запутанным, но это самый показательный пример который я смог придумать. Итак, вопрос, что будет выведено в консоль?
Кто читал прошлые посты уже догадываются какой ответ 🙃. Варианты которые тут могут быть: 0,0; 0,1; 1,0; 1,1. Разберем каждый из кейсов.
👉 Кейс первый 0 и 1. С этим кейсом все просто, представляем, что потоки у нас стартуют одновременно без задержек, тогда в переменную a
у нас сохранится значение 0, а в переменную b
значение 1, все просто.
👉 Кейс второй 0 и 0. В данном случае второй поток стартует с некоторой задержкой, и первый поток успевает изменить переменную y
. В этом случае в переменную a
у нас сохраняется значение 0 и в переменную b
тоже сохраняется значение 0.
👉 Кейс третий 1 и 1. В этом кейсе наоборот первый поток стартует с задержкой, и второй поток успевает затереть переменную x
. Тогда в переменную a
у нас сохранится значение 1, и в переменную b
значение 1, в целом все очевидно .
👉 Кейс четвертый 1 и 0. Самый загадочный из всех кейсов, воспроизвести его безумно сложно, практически нереально, но в теории возможно. Как такое может произойти? Вкратце, это еще одна оптимизация которую может сделать компилятор, процессор или окружение.
☝️Для начала договоримся, что действие это либо запись, либо чтение с переменной. Как вы все знаете компиляторы и процессоры очень сложные штуки 🧐. Компилятор может переставить действия местами если посчитает, что так будет быстрее. 💻 Процессор и JVM могут выполнять действия не в том порядке как они расположены в коде, и могут выполнять их как им это покажется нужным.
Еще раз наглядно на коде:
x = 3
y = 5
Нет никакой гарантии того, что операции присваивания в x
будет выполнена первой. Если у вас однопоточная программа, то эти перестановки вообще никак не влияют на ее выполнение, и можно вообще на это забить. 🧵Однако если у программы несколько потоков, и они еще и обращаются к одному и тому же месту, то всегда помните что JVM, компилятор или процессор могут переупорядочить действия.
Следовательно, в последнем кейсе это и произошло, инструкции с присваиванием поменялись местами. JVM спокойно могла их выполнить не в том, порядке в котором они расположены, так как это никак не повлияет на логику. Другими словами было:
var b = y
x = 1
Стало:
x = 1
var b = y
Избежать этих перестановок можно, а как и когда это нужно поговорим позже)
BY Dev Easy Notes

Share with your friend now:
tgoop.com/dev_easy_notes/35