энергозависимые переменные и барьер памяти в java

У меня есть структура данных, которая состоит из связанных узлов. Вы можете думать об этом как о простом LinkedList. Каждый узел списка состоит из некоторого значения и следующего поля, указывающего на другой узел, или нуля, если это последний узел. Первый узел работает как корень, он не имеет значения, он только указывает на следующий узел. Все остальные узлы практически неизменяемы, то есть после их создания ни их значение, ни их следующее поле не изменяются в течение срока службы, если только структура не удаляется, которая относится к конкретной ситуации.

Один (только один) поток добавляет новые узлы в начало списка. Это достигается путем создания нового объекта, установки его полей и установки следующего поля для объекта, на который указывает корень, а затем установки следующего поля корня на этот новый узел.

Другие узлы просматривают структуру только при чтении. У них есть ссылка на корневой узел, затем они просматривают другие узлы, пока не найдут то, что ищут, или не дойдут до конца списка.

Мой вопрос: достаточно ли сделать следующее поле нестабильным? Насколько я понимаю модель памяти Java, если основной поток (тот, который добавляет новые узлы) будет выполнять временную запись при добавлении нового узла, тогда все будет синхронизировано нормально, и никаких несоответствий не произойдет.

Также это правильно. предположить, что на архитектуре x86 чтение изменчивой переменной не приведет к снижению производительности? Поскольку другие потоки часто просматривают структуру, читая следующее поле, важно, чтобы это можно было делать свободно, без каких-либо барьеров памяти и т. Д.

У меня также есть еще одна проблема. Потоки, которые будут просматривать структуру, также будут содержать некоторые дополнительные узлы. Эти узлы будут полностью локальными для потока, то есть они будут использоваться только тем потоком, который их создал, и не будут использоваться совместно. Для этих дополнительных узлов необязательно, чтобы следующее поле было изменчивым. Более того, установка поля volatile next вызовет барьер памяти, который вызовет нежелательную потерю производительности. Интересно, есть ли способ избежать этого?В идеале было бы просто идеально, если бы следующее поле работало иногда как изменчивое поле, а иногда как обычное поле;) или если бы у меня был полный контроль и я мог бы самостоятельно создавать барьеры памяти, когда мне нужно.

Изменить:

Я также задавался вопросом, можно ли как-то синхронизировать все эти записи с другой изменчивой переменной? Например, какая-то другая совершенно не связанная статическая переменная? Поскольку изменяемая запись сбрасывает все ожидающие записи, не возможно ли, чтобы следующее поле не было изменчивым, а вместо этого была бы записана другая изменчивая переменная после того, как поток обновления выполнит всю работу?

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

Но, может быть, можно придумать такую ​​схему, которая была бы безопасной? Как насчет этого:

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

7
задан ciamej 30 June 2011 в 02:33
поделиться