Локална променлива, използвана за достъп до променлива променлива на екземпляр

Каква е целта или стойността на създаването на локална препратка към статична променлива променлива, която вече се съхранява като членско поле. Този код тук е от java.util.Scanner JDK 6b14 тук.

class Scanner {
    private static volatile Pattern linePattern;
    ...
    private static Pattern linePattern() {
        Pattern lp = linePattern;
        if (lp == null)
            linePattern = lp = Pattern.compile("...");
        return lp;
    }
    ...
}

Уроците по Java: „Четенето и писането са атомарни за всички променливи, декларирани като непостоянни (включително дълги и двойни променливи)... всяко записване в променлива променлива установява връзка преди да се случи с последващо четене на същата променлива."

Това означава, че четенето на препратката към обекта Pattern няма да се провали наполовина, защото се е променило. Ключовата дума volatile трябва да защитава точно тези видове достъп, така че не смятам, че дублиращата се локална променлива е предназначена да гарантира, че се връща валидна стойност.

Също така, мързеливата инициализация може да се извърши в полето член, без да е необходима междинна локална променлива:

if (linePattern == null) linePattern = Pattern.compile("...");

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


person xst    schedule 02.02.2013    source източник


Отговори (4)


Това "ускорява" нещата. Достъпът до volatile променливи е скъп. Използването може да се измъкне от това натоварване, като го присвоите на стекова променлива и получите достъп до нея вместо това

person Cratylus    schedule 02.02.2013

Мързелива инициализация, т.е. забавяне на работата, докато не е наистина необходимо.

person Wormbo    schedule 02.02.2013
comment
но защо тогава просто не инициализирате мързеливо полето член? - person xst; 03.02.2013
comment
Методът капсулира точно това. Използва се за получаване на стойността на полето и гарантира, че се инициализира, когато е необходимо. - person Wormbo; 03.02.2013
comment
if (linePattern == null) linePattern = new ... Това ще инициализира лениво полето член вместо локалната променлива. - person xst; 03.02.2013

Той гарантира, че върнатата стойност не е NULL - дори ако статичната променлива е настроена на NULL между проверка и връщане.

И в същото време е несинхронизирано мързеливо инициализиране с повторно инициализиране, ако е необходимо ;).

person Grzegorz    schedule 02.02.2013

За полета volatile linePattern може да се променя между различните редове. Копирането на препратката към локална променлива гарантира, че не можете да имате непоследователно състояние. Например, ако сте писали

 if (linePattern == null)
    linePattern = Pattern.compile("...");

тогава linePattern може да е спрял да бъде нулев, докато Pattern.compile се изпълняваше.

person Louis Wasserman    schedule 02.02.2013
comment
ключовата дума volatile гарантира, че четенията не се припокриват, както е посочено в препратката (която току-що добавих). Имате предвид volatile в C, където се използва за четене на картографирани в паметта IO устройства? - person xst; 03.02.2013
comment
Не, определено имам предвид volatile в Java. Препратката, която посочихте, означава, че linePattern няма да се припокрива по средата на едно конкретно четене или едно конкретно записване, но ако извършвате множество четения и/или множество записи, стойността може да бъде променена от други нишки между тези операции. - person Louis Wasserman; 03.02.2013