Проблема с многопоточностью заключается в следующем: представление на 10 000 футов памяти Java состоит в том, что существует один единственный фрагмент памяти, который используется всеми классами, всеми объектами, всеми загрузчиками классов и всеми потоками в работающей JVM - - все, что доступно из одного места в коде, доступно везде (с соответствующей ссылкой). Единственное исключение составляют регистры и стек выполнения, которые концептуально основаны на потоках.
Это чертовски хорошо работает с одним процессором, где потоки по очереди исполняются в одном наборе регистров, ALU и т.п. Но большинство современных компьютеров имеют несколько процессоров, поэтому несколько потоков могут выполняться буквально одновременно. Если бы все эти процессоры ссылались на одну и ту же физическую память, то (исходя из опыта реальной жизни) вы могли бы получить улучшение производительности примерно в 1,5 раза с 4 процессорами, и это привело бы к вырождению.
Таким образом, «кэш» используется для того, чтобы каждый процессор имел свою собственную небольшую частную копию битов и кусков большей памяти. Большую часть времени процессоры обращаются к совершенно разным областям памяти, поэтому это работает нормально, но иногда (например, при работе с каким-то «общим» объектом) они должны «бороться» за один и тот же набор байтов.
Решение состоит в том, чтобы установить протоколы, чтобы никакие два процессора не пытались изменить одни и те же места хранения в одно и то же время (или почти одно и то же), а также чтобы гарантировать, что один измененный процессор «сбрасывается» в основное хранилище, а другие процессоры сообщил об изменениях и посоветовал перезагрузить их представление об измененных данных.
Но (невероятно) неэффективно делать это после каждой операции (и, откровенно говоря, разработчики аппаратного обеспечения в значительной степени избежали этой проблемы и перенесли большую часть этой работы на программное обеспечение, чем это, вероятно, оправдано). Таким образом, схемы используются так, что сброс и перезагрузка данных происходит только на определенных «границах» или при выполнении определенных специальных типов ссылок.
Обратите внимание, что все это не имеет абсолютно никакого отношения к тому, является ли переменная "статической" или нет, и на самом деле это не имеет отношения к тому, являются ли объекты "неизменяемыми". Это присуще современной многопроцессорной аппаратной архитектуре в сочетании с моделью потоков Java.