0 added
0 removed
Original
2026-01-01
Modified
2026-03-10
1
<p>Теги: java, run(), race condition, memory consistency errors, multithreading, многопоточность java, thread, runtime, java memory model, ошибки многопоточного доступа к данным</p>
1
<p>Теги: java, run(), race condition, memory consistency errors, multithreading, многопоточность java, thread, runtime, java memory model, ошибки многопоточного доступа к данным</p>
2
<p>Принято считать, что многопоточность (<strong>multithreading</strong>) одна из самых сложных тем в программировании. В<a>первой заметке</a>мы постарались ответить на вопрос, почему так много разработчиков делают ошибки при создании приложений, которые работают более чем в одном потоке. В этой заметке разберём типы ошибок многопоточного доступа к данным:<strong>race condition</strong>и<strong>memory consistency errors</strong>. Но, перед тем как обсуждать ошибки доступа, давайте сначала разберёмся, что такое многопоточный доступ к данным.</p>
2
<p>Принято считать, что многопоточность (<strong>multithreading</strong>) одна из самых сложных тем в программировании. В<a>первой заметке</a>мы постарались ответить на вопрос, почему так много разработчиков делают ошибки при создании приложений, которые работают более чем в одном потоке. В этой заметке разберём типы ошибок многопоточного доступа к данным:<strong>race condition</strong>и<strong>memory consistency errors</strong>. Но, перед тем как обсуждать ошибки доступа, давайте сначала разберёмся, что такое многопоточный доступ к данным.</p>
3
<h2>В какой именно ситуации можно получить такие ошибки?</h2>
3
<h2>В какой именно ситуации можно получить такие ошибки?</h2>
4
<p>Мы уже упоминали, что поток в Java - это объект. У любого объекта есть класс. В классе могут быть методы и переменные. Представьте, что у вас есть класс-наследник от<strong>Thread</strong>, в котором вы в одной из переменных храните ссылку на массив. И этот массив вы получаете в конструкторе класса.</p>
4
<p>Мы уже упоминали, что поток в Java - это объект. У любого объекта есть класс. В классе могут быть методы и переменные. Представьте, что у вас есть класс-наследник от<strong>Thread</strong>, в котором вы в одной из переменных храните ссылку на массив. И этот массив вы получаете в конструкторе класса.</p>
5
<p>Пусть теперь, в<strong>runtime</strong>вы создаёте два объекта рассмотренного выше класса и передаёте в оба один и тот же массив. К элементам этого массива вы можете обращаться в методах<strong>run()</strong>ваших объектов. Одновременно. Из разных потоков исполнения. Вот это и есть многопоточный доступ к данным, которые хранит массив. Например, один поток может писать что-то в массив, а другой читать из него.</p>
5
<p>Пусть теперь, в<strong>runtime</strong>вы создаёте два объекта рассмотренного выше класса и передаёте в оба один и тот же массив. К элементам этого массива вы можете обращаться в методах<strong>run()</strong>ваших объектов. Одновременно. Из разных потоков исполнения. Вот это и есть многопоточный доступ к данным, которые хранит массив. Например, один поток может писать что-то в массив, а другой читать из него.</p>
6
<h2>Ошибки многопоточного доступа</h2>
6
<h2>Ошибки многопоточного доступа</h2>
7
<p>Рассмотрим теперь ситуацию, когда два рассмотренных выше потока собираются увеличить значение числа, которое записано в первой ячейке массива. Последовательность событий такая: - первый поток прочитал значение и увеличил его, - второй поток прочитал то же значение, - первый записал новое, - второй увеличил значение и записал его.</p>
7
<p>Рассмотрим теперь ситуацию, когда два рассмотренных выше потока собираются увеличить значение числа, которое записано в первой ячейке массива. Последовательность событий такая: - первый поток прочитал значение и увеличил его, - второй поток прочитал то же значение, - первый записал новое, - второй увеличил значение и записал его.</p>
8
<p>В результате вместо ожидаемого увеличения значения на 2 мы получим увеличение на 1, так как результат работы первого потока был "перетёрт" результатом работы второго. Такая ситуация происходит из-за неатомарности операции увеличения значения числа. И является разновидностью ошибки многопоточного доступа -<strong>race condition</strong>.</p>
8
<p>В результате вместо ожидаемого увеличения значения на 2 мы получим увеличение на 1, так как результат работы первого потока был "перетёрт" результатом работы второго. Такая ситуация происходит из-за неатомарности операции увеличения значения числа. И является разновидностью ошибки многопоточного доступа -<strong>race condition</strong>.</p>
9
<p>Вторая возможная ошибка многопоточного доступа -<strong>memory consistency error</strong>происходит из-за того, что разные потоки могут быть физически исполнены на различных процессорах вашего компьютера. Каждый процессор может закэшировать значение переменной у себя, не записывая её в общую память. В результате разные потоки могут видеть в одно и тоже время разное значение переменной.</p>
9
<p>Вторая возможная ошибка многопоточного доступа -<strong>memory consistency error</strong>происходит из-за того, что разные потоки могут быть физически исполнены на различных процессорах вашего компьютера. Каждый процессор может закэшировать значение переменной у себя, не записывая её в общую память. В результате разные потоки могут видеть в одно и тоже время разное значение переменной.</p>
10
<p>Описанные выше проблемы призвана решить<strong>Java Memory Model</strong>. Если не знаете, что это такое и как именно она может помочь Java-разработчику, спрашивайте в комментариях!</p>
10
<p>Описанные выше проблемы призвана решить<strong>Java Memory Model</strong>. Если не знаете, что это такое и как именно она может помочь Java-разработчику, спрашивайте в комментариях!</p>
11
11