Подтвердить что ты не робот

Статические переменные и многопоточность в java

Является ли статический член класса присутствующим только как один экземпляр для процесса или потока? Значение каждого потока имеет свою собственную копию статической переменной-члена класса?

Мое предположение для каждого процесса, я прав?

4b9b3361

Ответ 1

Статические поля дали одно значение для каждого загрузчика классов.

Если вам нужно значение для потока, сделайте статический ThreadLocal<T>.

Ответ 2

Как уже упоминалось, поля static имеют одно значение для класса-загрузчика. Однако я думал, что прокомментирую следующий текст вашего вопроса:

каждый поток имеет свою собственную копию статической переменной-члена класса

Это правильно, хотя дьявол находится в деталях. Каждый поток может иметь свою собственную копию поля в своем собственном локальном пространстве/кеше, если поле не было помечено volatile, которое заставляет поле быть окружено барьером памяти, что вызывает синхронизацию памяти при каждом доступе/обновлении.

Без volatile любые обновления и чтение в поле static будут выполняться в локальном хранилище потоков и обновляются только тогда, когда поток пересекает барьер памяти. Без барьеров памяти нет никаких гарантий вокруг порядка операций с данными и когда обновления будут совместно использоваться другими потоками.

Здесь достойная страница о модель памяти Java и хорошая обзор некоторых проблем.

Ответ 3

Существует одна копия переменной static для каждого загрузчика классов, загружающих этот класс. Это более или менее средство для каждого процесса, однако вам нужно знать о различии.

например. когда два веб-приложения имеют один и тот же класс в комплекте, класс будет загружен дважды, таким образом, имея две копии того же поля static.

Если вам нужна переменная, имеющая независимое значение на основе потока, посмотрите ThreadLocal.

Ответ 4

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/variables.html

Переменные класса (статические поля) Переменная класса - это любое поле, объявленное с помощью статического модификатора; это говорит компилятору, что существует только одна копия этой переменной, независимо от того, сколько раз экземпляр класса был создан. Поле, определяющее количество передач для определенного вида велосипеда, может быть помечено как статическое, так как концептуально одинаковое количество передач будет применяться ко всем экземплярам. Код static int numGears = 6; создаст такое статическое поле. Кроме того, можно добавить ключевое слово final, чтобы указать, что количество передач никогда не изменится.

Нитки не имеют отношения к этому. (Однако, если вы используете несколько загрузчиков классов в своем приложении, вы, вероятно, находитесь в точке, где вы это понимаете).

Ответ 5

Проблема с потоковой передачей такова: "10 000-футовое" представление памяти Java состоит в том, что есть один блок памяти, который разделяется всеми классами, всеми объектами, всеми загрузчиками классов и всеми потоками в запущенной JVM - - все, что доступно с одного места в коде, доступно везде (с учетом соответствующей ссылки). Единственное исключение - это регистры и стеки выполнения, которые концептуально основаны на потоках.

Это хорошо работает с одним процессором, где потоки по очереди исполняются в одном наборе регистров и ALU и т.д. Но большинство современных компьютеров имеют несколько процессоров, поэтому несколько потоков могут выполняться буквально в одно и то же время. Если эти процессоры должны были ссылаться на одну и ту же физическую память, тогда (на основе реального опыта), вы могли бы получить только 1,5-кратное повышение производительности с 4-мя процессорами, и оно выродилось бы оттуда.

Итак, используется "кеш", так что каждый процессор имеет свою собственную небольшую частную копию бит и частей большей памяти. В большинстве случаев процессоры обращаются к совершенно другим областям памяти, поэтому это работает отлично, но иногда (как при работе с каким-то "общим" объектом) они должны "сражаться" над одним и тем же набором байтов.

Решение состоит в том, чтобы установить протоколы, чтобы ни один из двух процессоров не попытался изменить одни и те же места хранения в одно и то же время (или почти одинаковые) и гарантировать, что один из процессоров изменился, чтобы "сбросить" в основное хранилище, а другие процессоры узнали об изменениях и посоветовали перезагрузить их взгляд на измененные данные.

Но он (невероятно) неэффективен для этого после каждой операции (и, откровенно говоря, аппаратные дизайнеры в значительной степени уклонились от этой проблемы и больше наложили эту работу на программное обеспечение, чем это, вероятно, оправдано). Таким образом, схемы используются так, что сброс и перезагрузка данных происходит только на определенных "границах" или когда выполняются определенные специальные типы ссылок.

Обратите внимание, что все это абсолютно не имеет никакого отношения к тому, является ли переменная "статической" или нет, и она не имеет никакого отношения к тому, являются ли объекты "неизменными". Он присущ современной многопроцессорной аппаратной архитектуре в сочетании с моделью потоков Java.

Ответ 6

Так как SLaks предложил его один на JVM, но будьте осторожны, что два потока, удерживающие блокировку на одной и той же статической ссылке, будут блокировать друг друга, потому что существует только одна такая ссылка на vm. Но они не будут блокировать потоки, ссылаясь на переменные экземпляра.

Ответ 7

Фактически переменная класса соответствует классу, в ней используется только одна память, поэтому изменения, сделанные каждым экземпляром класса, могут изменять переменную класса.