根据Apple Docs NSCalendar is not thread-safe。
使用static method currentCalendar
时,如何确保线程安全?
任何库都可以调用相同的方法。如何锁定访问权限?
答案 0 :(得分:0)
您可以使用NSLock。
NSLock *lock = [[NSLock alloc] init];
和
[lock lock];
//calendar
[lock unlock];
答案 1 :(得分:0)
我希望创建一个Calendar是线程安全的(每次调用-currentCalendar你得到一个新实例),同时变异实例不会。
答案 2 :(得分:0)
您可能希望使用代理来包装同步块中的所有方法。请参阅下面的我的类BMProxy(threadSafe设置为YES)。我使用这个类来跨多个线程重用NSDateFormatters和NSCalendars,这就像一个魅力。您也可以将它用于其他非线程安全类的实例。
用法例如如下:
+ (NSCalendar *)threadSafeCalendar {
static NSCalendar *calender = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSCalendar *c = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[c setTimeZone:[NSTimeZone timeZoneWithName:@"CET"]];
calender = (NSCalendar *)[BMProxy proxyWithObject:c threadSafe:YES retained:YES];
});
return calender;
}
BMProxy类:
#import <Foundation/Foundation.h>
/**
Proxy that delegates all messages to the specified object
*/
@interface BMProxy : NSProxy {
@private
__weak NSObject *_object;
__strong NSObject *_retainedObject;
BOOL _threadSafe;
}
/**
The target object of the proxy.
*/
@property(readonly, weak) NSObject *object;
/**
Whether the proxy should be thread-safe (make all methods synchronized) or not.
*/
@property(atomic, assign) BOOL threadSafe;
/**
Initializer with the designated target object.
Defaults to threadSafe = NO and retained = YES.
@param object The proxied object
*/
- (id)initWithObject:(NSObject *)object;
/**
Initializer with the designated target object and whether the proxy should be thread-safe or not.
Defaults to retained = YES.
@param object The proxied object
@param threadSafe Whether the proxy should synchronize all methods or not.
*/
- (id)initWithObject:(NSObject *)object threadSafe:(BOOL)threadSafe;
/**
Designated initializer.
The retained parameter determines whether the target object is retained or not.
*/
- (id)initWithObject:(NSObject *)object threadSafe:(BOOL)threadSafe retained:(BOOL)retained;
+ (BMProxy *)proxyWithObject:(NSObject *)object threadSafe:(BOOL)threadSafe retained:(BOOL)retained;
@end
@implementation BMProxy
@synthesize threadSafe = _threadSafe;
@synthesize object = _object;
+ (BMProxy *)proxyWithObject:(NSObject *)object threadSafe:(BOOL)threadSafe retained:(BOOL)retained {
return [[BMProxy alloc] initWithObject:object threadSafe:threadSafe retained:retained];
}
- (id)initWithObject:(NSObject *)theObject {
return [self initWithObject:theObject threadSafe:NO retained:YES];
}
- (id)initWithObject:(NSObject *)theObject threadSafe:(BOOL)b {
return [self initWithObject:theObject threadSafe:b retained:YES];
}
- (id)initWithObject:(NSObject *)theObject threadSafe:(BOOL)b retained:(BOOL)retained {
_object = theObject;
if (retained) {
_retainedObject = theObject;
}
self.threadSafe = b;
return self;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [_object methodSignatureForSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
if (self.threadSafe) {
@synchronized(_object) {
[anInvocation setTarget:_object];
[anInvocation invoke];
}
} else {
[anInvocation setTarget:_object];
[anInvocation invoke];
}
}
- (BOOL)respondsToSelector:(SEL)aSelector {
BOOL responds = [super respondsToSelector:aSelector];
if (!responds) {
responds = [_object respondsToSelector:aSelector];
}
return responds;
}
@end