Проверенная дважды Статья блокировки

Попробуйте, добавив его в HTML-файл. У меня было точно такое же требование, и это был самый простой метод, который я нашел ...

<html>
    <body>
        <embed style="height: 100%; width: 100%;" src="data:application/pdf;base64,YOUR_BASE64_STRING_GOES_HERE" type="application/pdf"></object>
    </body>
</html>
11
задан GingerPlusPlus 13 February 2016 в 16:46
поделиться

10 ответов

Точка блокировки дважды должна была попытаться предотвратить неисправные записи. Модель памяти указывает, где переупорядочения могут произойти, частично с точки зрения блокировок. Блокировка гарантирует, чтобы никаких записей (включая любого в одноэлементном конструкторе), казалось, не происходило после "экземпляра = inst"; строка.

Однако для движения глубже в предмет я рекомендовал бы статью Bill Pugh. И затем никогда не делайте попытку его :)

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

Статья относится к пред5.0 Моделям памяти Java (JMM). Под той моделью, оставляя синхронизируемый блокируют вызванные записи к оперативной памяти. Таким образом, это, кажется, попытка удостовериться, что объект Singleton выставлен перед ссылкой на него. Однако это не вполне работает, потому что запись к экземпляру может быть перемещена вверх в блок - мотель плотвы.

Однако пред5.0 моделей правильно никогда не реализовывались. 1.4 должен следовать 5,0 моделям. Классы инициализируются лениво, таким образом, Вы могли бы также просто записать

public static final Singleton instance = new Singleton();

Или лучше, не используйте одиночные элементы, поскольку они являются злыми.

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

Jon Skeet прав: прочитайте статью Bill Pugh. Идиома, которую использует Hans, является точной формой, которая не будет работать и не должна использоваться.

Это небезопасно:

private static Singleton instance;

public static Singleton getInstance() {
  if (instance == null) {
    synchronized(Singleton.class) {
      if (instance == null) {
        instance = new Singleton();
      }
    }
  }
  return instance;
}

Это также небезопасно:

public static Singleton getInstance()  
{
    if (instance == null)
    {
        synchronized(Singleton.class) {      //1
            Singleton inst = instance;         //2
            if (inst == null)
            {
                synchronized(Singleton.class) {  //3
                    inst = new Singleton();        //4
                }
                instance = inst;                 //5
            }
        }
    }
    return instance;
}

Не делайте ни одного из них, никогда.

Вместо этого синхронизируйте целый метод:

    public static synchronized Singleton getInstance() {
      if (instance == null) {
        instance = new Singleton();
      }
      return instance;
    }

Если Вы не получаете этот объект огромное количество раз в секунду, хит производительности, в реальном выражении, незначителен.

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

Я покрываю набор этого здесь:

http://tech.puredanger.com/2007/06/15/double-checked-locking/

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

Хорошо, но в статье было сказано это

Код в Списке 7 не работает из-за текущего определения модели памяти. Спецификация языка Java (JLS) требует, чтобы код в синхронизируемом блоке не был перемещен из синхронизируемого блока. Однако это не говорит, что код не в синхронизируемом блоке не может быть перемещен в синхронизируемый блок.

И также кажется, что JVM делает следующий перевод для "псевдокодирования" в ASM:

public static Singleton getInstance()
{
  if (instance == null)
  {
    synchronized(Singleton.class) {      //1
      Singleton inst = instance;         //2
      if (inst == null)
      {
        synchronized(Singleton.class) {  //3
          //inst = new Singleton();      //4
          instance = new Singleton();               
        }
        //instance = inst;               //5
      }
    }
  }
  return instance;
}

До сих пор точка никаких записей после "instance=inst" не выполняется?

Я прочитаю теперь статью, спасибо за ссылку.

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

В соответствии с рекомендацией стрельбы по тарелочкам John:

Однако для движения глубже в предмет я рекомендовал бы статью Bill Pugh. И затем никогда не делайте попытку его :)

И вот ключ для второго синхронизирующего блока:

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

Так в основном, с Внутренним синхронизирующим блоком, мы пытаемся "обмануть" JMM создание Экземпляра в синхронизирующем блоке, вынудить JMM выполнить то выделение перед синхронизирующим законченным блоком. Но проблема здесь состоит в том, что JMM возглавляет нас и перемещает присвоение, которое является перед синхронизирующим блоком в синхронизирующем блоке, кладя обратно нашу проблему к beginnig.

Это - то, что я понял от тех статей, действительно интересных, и еще раз благодарю за ответы.

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

Начиная с Java 5 можно сделать перепроверяемую работу блокировки путем объявления энергозависимого поля.

См. http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html для полного объяснения.

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

Относительно этой идиомы существует очень желательная и разъясняющаяся статья:

http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html?page=1

С другой стороны, я думаю, что означает dhighwayman.myopenid, то, почему писатель поместил синхронизируемый блок того, относящийся к тому же классу (синхронизировался (Singleton.class)) в другом синхронизируемом блоке, относящемся к тому же классу. Это может произойти как новый экземпляр (Singleton inst = экземпляр;) создается в том блоке, и гарантировать это, чтобы быть ориентированным на многопотоковое исполнение необходимо записать, что другой синхронизировался.

Иначе я не вижу смысла.

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

Посмотрите Google Tech Talk на Модели памяти Java для действительно хорошего введения в тонкости JMM. Так как это отсутствует здесь, я также хотел бы указать на Параллелизм Java 'блога Jeremy Mansons' особенно сообщение на Проверенной дважды блокировке (любой, кто что-либо в мире Java, кажется, имеет статью об этом :).

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

Для Java 5 и лучше на самом деле есть вариант DoubleChecked, который может быть лучше, чем синхронизировать весь доступность. Это также упоминается в Декларации с двойной проверкой :

class Foo {
    private volatile Helper helper = null;
    public Helper getHelper() {
        if (helper == null) {
            synchronized(this) {
                if (helper == null)
                    helper = new Helper();
            }
        }
        return helper;
    }
}

Разница в ключее здесь является использование волатиле в переменной декларации - в противном случае он не работает, и это делает Во всяком случае, не работать в Java 1.4 или меньше.

0
ответ дан 3 December 2019 в 01:39
поделиться
Другие вопросы по тегам:

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