2014-11-20 3 views
0

Может ли кто-нибудь дать объяснение на низком уровне о том, почему singletonInstance не установлен в nil и как dispatch_one работает с onceToken?Низкий уровень Singleton Instance

+ (id)singletonInstance { 
    static FOO *singletonInstance = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     singletonInstance = [[self alloc] init]; 
    }); 
    return singletonInstance; 
} 

ответ

0

singletonInstance переменная является набор для nil, а потому, что он имеет static сферу (т.е. он ведет себя как глобальный, который доступен только в рамках этого метода), он устанавливается в nil только один раз (не каждый время, которое этот метод называется). Итак, как только singletonInstance установлен в конкретный экземпляр этого класса внутри блока dispatch_once, вы можете быть уверены, что переменная не будет сброшена на nil позже.

Звонок dispatch_once просто гарантирует, что блок кода вызывается один раз и только один раз (и переменная static, onceToken, является тем, как она отслеживает, была ли она еще вызвана). Преимущество шаблона dispatch_once, в отличие от других подходов, заключается в том, что он потокобезопасен (поэтому, даже если несколько потоков пытаются одновременно вызвать singletonInstance, он будет вызван только один раз, избегая условий гонки).

Общей проблемой здесь является использование ключевого слова static в объявлениях переменных. Квалификатор static указывает, что переменная не является локальной переменной, уникальной для конкретного метода, и не является переменной экземпляра, уникальной для конкретного экземпляра класса. Это переменная, которая эффективно распределяется между всеми вызовами этого метода singletonInstance (или, по крайней мере, до тех пор, пока приложение не будет завершено). Таким образом, переменные static являются эффективным механизмом для отслеживания экземпляра singleton, а также хорошей ссылкой, которую dispatch_once может использовать для отслеживания того, был ли он вызван или нет.

Смежные вопросы