Классический сценарий мертвой блокировки является A, фиксатор X и хочет получить блокировку Y, в то время как B является фиксатором Y и хочет получить блокировку X. Так как ни один не может завершить то, что они пытаются сделать, оба закончат тем, что ожидали навсегда (если тайм-ауты не будут использоваться).
В этом случае мертвой блокировки можно избежать, если A и B получают блокировки в том же порядке.
Допустим, у вас есть указатель myView
, определенный в интерфейсе вашего класса:
@interface MyClass {
UIView *myView;
}
@end
Затем в вашем коде в какой-то момент вы можете освободить эту переменную:
[myView release];
После этого указатель myView
не будет указывать на nil, но будет указывать на адрес в памяти объекта, который может больше не существовать (поскольку вы только что его отпустили). Итак, если вы сделаете что-нибудь после этого, например:
[myView addSubview:otherView];
, вы получите сообщение об ошибке.
Если, с другой стороны, вы сделаете это:
[myView release];
myView = nil;
...
[myView addSubview:otherView];
вызов addSubview
не будет иметь никакого негативного воздействия, поскольку сообщения, равные нулю, игнорируются .
В качестве следствия вы можете увидеть предложения об использовании сохранения
свойств, таких как:
@property(retain) UIView *myView;
, а затем в коде просто выполните:
self.myView = nil;
Таким образом, синтезированный метод доступа освободит старый объект и установит для ссылки значение nil в одной строке кода. Это может оказаться полезным, если вы хотите убедиться, что все ваши свойства освобождены и установлены в ноль.
Одна вещь, которую вы никогда не должны забывать, это то, что управление памятью осуществляется с помощью keep
release
, а не путем присвоения nil. Если у вас есть объект с сохраняемым счетчиком, равным 1, и назначьте nil его единственной переменной, у вас будет утечка памяти:
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0,0,10,10)];
view = nil;
// You just leaked a UIView instance!!!