NSLock "контроллер" класс
Я пишу многопоточное приложение для iPhone и использую NSLock, чтобы убедиться, что некоторые операции (например, загрузка звуков из файла) будут работать как атомарные. Чтобы упростить получение блокировок из разных частей моего приложения, я написал следующий класс, который позволяет мне блокировать и разблокировать блокировки, просто передавая NSString с именем. Если такой блокировки не существует, он создает ее и сохраняет на будущее. Я проверил его, и он, кажется, работает нормально (поскольку он просто обеспечивает доступ к объектам NSLock и не изменяет их поведение).
Мой вопрос: нормально ли иметь и использовать такой класс, или у меня есть какое-то недопонимание в концепции замков?
Locker.h
#import <Foundation/Foundation.h>
@interface Locker : NSObject { }
+ (void) purgeLocks;
+ (NSLock*) lockWithName: (NSString*) name;
+ (void) lock: (NSString*) name;
+ (void) unlock: (NSString*) name;
+ (BOOL) tryLock: (NSString*) name;
@end
Locker.m
#import "Locker.h"
static NSMutableDictionary* locks = nil;
@implementation Locker
+ (void) initialize {
locks = [[NSMutableDictionary dictionary] retain];
}
+ (void) purgeLocks {
[locks release];
[Locker initialize];
}
+ (NSLock*) lockWithName: (NSString*) name {
NSLock* lock = nil;
@synchronized([Locker class]) {
lock = [locks objectForKey: name];
if(!lock) {
lock = [[[NSLock alloc] init] autorelease];
[lock setName: name];
[locks setObject: lock forKey: name];
}
}
return lock;
}
+ (void) lock: (NSString*) name {
[[Locker lockWithName: name] lock];
}
+ (void) unlock: (NSString*) name {
[[Locker lockWithName: name] unlock];
}
+ (BOOL) tryLock: (NSString*) name {
return [[Locker lockWithName: name] tryLock];
}
@end
2 ответа
Это выглядит довольно тяжелым для меня. Вы уверены, что не можете упростить дизайн? (GCD приходит на ум.) Почти каждое iOS-приложение является многопоточным, и ИМХО редко можно встретить таких помощников блокировки, как вы написали. Если есть место, где сияет принцип KISS, я уверен, что это многопоточность.
@synchronized
медленно, избегайте этого. Выделить блокировку в + initialize
и используйте это вместо этого. Но я бы выбрал синглтон вместо использования методов класса, но это более или менее дело вкуса.
Основным недостатком вашего подхода является то, что вы должны заблокировать блокировку, чтобы получить другую блокировку. В сильно многопоточном приложении этот мета-замок (ваш текущий @synchronized
) может стать узким местом производительности, даже если все потоки хотят получить доступ к различным блокировкам.