Ank*_*ava 3 iphone singleton objective-c thread-safety
如何在objective-c中创建线程安全的单例对象.例如.如果我有一个共享数据控制器是一个单例对象,如果两个或多个线程同时访问它会发生什么?或者这些对象默认具有线程安全性.?
更新:
是否在这种情况下,datacontroller属性中的对象决定它是否是线程安全的?就像我的datacontroller有NSMutableArray并且它设置为nonatomic它不会是线程安全的.在这种情况下,它的价值会发生什么变化?
更新:2
实际上做了 @synchronized(self) 什么..?
如果数据控制器不是线程安全的,那么可能会发生未定义的行为 - 不惜一切代价避免它=)
默认情况下,NSObjects绝对不是线程安全的.使用原子属性不会使类线程安全(添加因为它是一个流行的误解).
典型的解决方案是确保所有可变状态都受到适当锁定(例如互斥锁或保护)的保护@synchronized.
当我说可变状态时,我指的是一个可以在外部或内部发生变异的对象.如果您不确定,请锁定以确保从多个线程读取或写入类型.这必须发生在阅读和写作 - 总是.如果你有很多阅读,一个readwrite锁可能是一个更好,更专业的锁.
要更详细地回答,您必须发布一些代码.
更新
是否在这种情况下,datacontroller属性中的对象决定它是否是线程安全的?就像我的datacontroller有NSMutableArray并且它设置为nonatomic它不会是线程安全的.在这种情况下,它的价值会发生什么变化?
把它想象成具有传递性.你的NSMutableArray,它拥有的对象以及它们的所有外部引用必须以线程安全的方式使用,你必须跟踪所有这些.通常,您首先要减少共享的可变状态.而不是给客户端提供对数组的引用,而是为它们提供数组所拥有的元素的副本.同时,使用锁保护所有读取,写入和元素复制.
为简单起见,我将演示如何使用@synchronize:
@interface MONCookie : NSObject <NSCopying>
- (NSString *)name;
@end
@interface MONDataController : NSObject
{
@private
NSMutableArray * cookies; // << MONCookie[]
}
- (void)addCookie:(MONCookie *)cookie;
- (MONCookie *)cookieWithName:(NSString *)name;
@end
@implementation MONDataController
- (id)init
{
// no lock required here
self = [super init];
if (nil != self) {
cookies = [NSMutableArray new];
}
return self;
}
- (void)dealloc
{
// no lock required here
[cookies release], cookies = nil;
[super dealloc];
}
- (void)addCookie:(MONCookie *)cookie
{
@synchronized(self) { // now accessing cookies - lock required
[cookies addObject:cookie];
}
}
- (MONCookie *)cookieWithName:(NSString *)name
{
MONCookie * ret = nil;
@synchronized(self) { // now accessing cookies - lock required
for (MONCookie * at in cookies) {
if ([at.name isEqualToString:name]) {
ret = [at copy]; // << give them a copy if cookie is not threadsafe
}
}
}
return [ret autorelease];
}
@end
Run Code Online (Sandbox Code Playgroud)
更新2
@synchronized设置对象级锁定.您可以将其视为您的实例独有的递归(或可重入)锁.与其他锁定方法相比,它也很慢.上面的代码使用它,它是线程安全的,等同于持有递归锁,并在@synchronized边界处锁定和解锁.
@interface MONCookie : NSObject <NSCopying>
{
@private
NSRecursiveLock * lock;
}
@end
@implementation MONCookie
- (id)init
{
self = [super init];
if (nil != self) {
lock = [NSRecursiveLock new];
}
return self;
}
- (void)temperatureDidIncrease
{
// ...
}
- (void)bake
{
// use the same lock for everything
// do not mix @synchronized in some places, and use of the lock
// in others. what you use to protect the data must remain consistent
//
// These are equivalent approaches to protecting your data:
{ // @synchronized:
@synchronized(self) {
[self temperatureDidIncrease];
}
}
{ // using the lock:
[lock lock];
[self temperatureDidIncrease];
[lock unlock];
}
}
@end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3899 次 |
| 最近记录: |