#deepjava #otus

Принято считать, что многопоточность (multithreading) одна из самых сложных тем в программировании. И мы решили посвятить ей не одну, а несколько заметок, которые вы сможете найти по хэштегу #deepjava.



В этой заметке мы разберем типы ошибок многопоточного доступа к данным: race condition и memory consistency errors.



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



Мы уже упоминали в предыдущем посте, что поток в Java это объект. У любого объекта есть класс. В классе могут быть методы и переменные. Представьте, что у вас есть класс — наследник от Thread, в котором вы в одной из переменных храните ссылку на массив. И этот массив вы получаете в конструкторе класса.



Пусть теперь, в runtime вы создаете два объекта рассмотренного выше класса и передаете в оба один и тот же массив. К элементам этого массива вы можете обращаться в методах run() ваших объектов. Одновременно. Из разных потоков исполнения. Вот это и есть многопоточный доступ к данным которые хранит массив.

Например, один поток может писать что-то в массив, а другой читать из него.



Рассмотрим теперь ситуацию, когда два рассмотренных выше потока собираются увеличить значение числа, которое записано в первой ячейке массива. Со следующей последовательностью событий: первый поток прочитал значение и увеличил его, второй поток прочитал то же значение, первый записал новое, второй увеличил значение и записал его. В результате вместо ожидаемого увеличения значения на 2 мы получим увеличение на 1, так как результат работы первого потока был “перетерт” результатом работы второго. Такая ситуация происходит из-за неатомарности операции увеличения значения числа. И является разновидностью ошибки многопоточного доступа — race condition.



Вторая возможная ошибка многопоточного доступа — memory consistency error происходит из-за того, что разные потоки могут быть физически исполнены на различных процессорах вашего компьютера. Каждый процессор может закэшировать значение переменной у себя, не записывая ее в общую память. В результате разные потоки могут видеть в одно и тоже время разное значение переменной.



Описанные выше проблемы призвана решить Java Memory Model. Что это такое и как именно она может помочь разработчику, мы рассмотрим в следующих заметках. И, подробно разберем на занятиях курса “Разработчик Java” в OTUS о которых вы можете узнать подробнее перейдя по ссылке:

otus.ru/promo/java-2017/?utm_source=telegram&utm_medium=internal&utm_campaign=java&utm_content=deeppost&utm_term=27.09