Интернет магазин китайских планшетных компьютеров |
|
Компьютеры - Double checked locking - Пример использования в Java02 мая 2011Оглавление: 1. Double checked locking 2. Пример использования в Java 3. Пример использования в C# Рассмотрим следующий код на языке Java, взятый из:
// Однопоточная версия
class Foo {
private Helper helper = null;
public Helper getHelper {
if
helper = new Helper;
return helper;
}
// и остальные члены класса…
}
Этот код не будет корректно работать в многопоточной программе. Метод
// Правильная, но "дорогая" по времени выполнения многопоточная версия
class Foo {
private Helper helper = null;
public synchronized Helper getHelper {
if
helper = new Helper;
return helper;
}
// и остальные члены класса…
}
Этот код работает, но он вносит дополнительные накладные расходы на синхронизацию. Первый вызов
// Неработающая многопоточная версия
// Шаблон "Double-Checked Locking"
class Foo {
private Helper helper = null;
public Helper getHelper {
if {
synchronized {
if {
helper = new Helper;
}
}
}
return helper;
}
// и остальные члены класса…
}
На интуитивном уровне, этот код кажется корректным. Однако, существуют некоторые проблемы, которых следует избежать. Представим себе, что события в многопоточной программе протекают так:
Одна из опасностей использования блокировки с двойной проверкой в J2SE 1.4 состоит в том, что часто кажется, что программа работает корректно. Во-первых, рассмотренная ситуация будет возникать не очень часто; во-вторых, сложно отличить корректную реализацию данного шаблона от такой, которая имеет описанную проблему. В зависимости от компилятора, распределения планировщиком процессорного времени для потоков, а также природы других работающих конкурентных процессов, ошибки, спровоцированные с некорректной реализацией блокировки с двойной проверкой, обычно происходят бессистемно. Воспроизведение таких ошибок обычно затруднено. Можно решить проблему при использовании J2SE 5.0. Новая семантика ключевого слова
// Работает с новой семантикой volatile
// Не работает в Java 1.4 и более ранних версиях из-за семантики volatile
class Foo {
private volatile Helper helper = null;
public Helper getHelper {
if {
synchronized {
if
helper = new Helper;
}
}
return helper;
}
// и остальные члены класса…
}
Было предложено много вариантов блокировки с двойной проверкой, которые явно не сообщают то, что объект полностью сконструирован, и все они являются некорректными. Просмотров: 3133
|