Энергозависимый или синхронизировался для типа примитива?

Согласно зарегистрированный отчет об ошибках существует обходное решение:

Эта недокументированная опция отключит perfdata опцию:
-XX:-UsePerfData

стоит упомянуть, что это - функция хотя, не ошибка. Вышеупомянутое обходное решение просто отключает опцию.

15
задан Pang 24 August 2015 в 02:34
поделиться

4 ответа

Если вы обнаружите, что блокировка самого объекта слишком тяжелая, то лучше всего использовать синхронизацию. До Java 1.5 volatile мог быть хорошим выбором, но теперь volatile может иметь очень большое влияние, заставляя упорядочивать инструкции в методе, в котором происходит присваивание. Создайте отдельный объект ( private final Object X_LOCK = new Object (); ) и синхронизируйте с ним при установке или получении значения этого двойника. Это даст вам прекрасный уровень контроля над блокировкой, который, как кажется, вам нужен.

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

5
ответ дан 1 December 2019 в 01:23
поделиться

Что вы пытаетесь сделать? Ключевые слова synchronized и volatile - это механизмы в Java, которые можно использовать для обеспечения того, чтобы разные потоки считывали одни и те же данные согласованные значения. В частности, они позволяют вам рассуждать об отношениях происходит до в ваших программах.

Вы просто не можете избежать использования одного из volatile или synchronized для того, чтобы правильно обращаться к полям, отличным от final , в многопоточной программе. Тем не менее, основная причина, по которой вам, вероятно, потребуется синхронизированный вместо volatile , является требование использования атомарных операций сравнения и установки (т.е. он не принимать во внимание производительность ). Например, в многопоточной программе:

volatile int i = 0;

public void foo() { 
    if (i == 0) i = i + 1;
}

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

int i = 0;

public synchronized void foo() {
    if (i == 0) i = i + 1;
}

. Так что же вы предпочтете? Что ж, если у вас есть несколько потоков, изменяющих поле в зависимости от значения этого поля (т.е. сравнивать и устанавливать), тогда synchronized - единственное безопасное решение.

Также стоит сказать: производительность накладные расходы synchronized не являются проблемой (в подавляющем большинстве случаев). Проблемы с производительностью синхронизации обычно возникают из-за ненужных узких мест в коде, взаимоблокировок или живых блокировок и при необходимости могут быть устранены.

26
ответ дан 1 December 2019 в 01:23
поделиться

volatile, безусловно, подойдет, если вы только выполняете задание. Я уверен, что вы знаете, но поскольку он был поднят: если вы хотите выполнять более сложные операции (например, увеличивать значение), вам нужно будет синхронизировать. i ++ никогда не является потокобезопасным для любых типов переменных. Вам нужно синхронизировать. i ++ и тому подобное, поскольку на самом деле это более одной операции.

Нет: было указано, что вы можете использовать AtomicDouble, но в настоящее время AtomicDouble в java.util.concurrent.atomic

Если вы выполняете несколько операций на x, что требует установки нового значения в конце, это можно сделать потокобезопасным способом без каких-либо блокировок, и сделать это потокобезопасным, используя сравнение и установку. Пример:

AtomicLong x = new AtomicLong(SomeValue);
public void doStuff() {
  double oldX;
  double newX;
  do {
    oldX = x.get();
    newX = calculateNewX(oldX);
  } while (!x.compareAndSet
      (Double.doubleToLongBits(oldX), Double.doubleToLongBits(newX)));

Это работает, потому что compareAndSet будет видеть, изменилось ли значение x с момента последнего чтения. Если x изменился, вы будете вынуждены выполнить вычисление снова и снова попытаться установить его.

Конечно, вы могли бы реализовать свой собственный AtomicDouble вместо преобразования doubleToLongBits. Взгляните на AtomicFieldUpdater.

3
ответ дан 1 December 2019 в 01:23
поделиться

KDSRathore, вы можете использовать некоторые явные блокировки или создать фиктивный объект Object = new Object (), с которым вы синхронизируете в установщике / получателе этого двойника

2
ответ дан 1 December 2019 в 01:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: