2011-09-05 26 views
2

我想知道如果以下是最好的方法来读取并复制一个可能被另一个锁定的对象线?对另一个可能被另一个线程锁定的对象进行“脏读”的最佳方法-c

-(NSObject*) getCopyOfActiveObjectsOfType:(Class) objectClass 
{ 
    NSMutableArray* copy = [NSMutableArray arrayWithArray:[self.activeObjects objectForKey:objectClass]]; 

    return copy; 
} 

我有几个类似于下面的方法,锁定有问题的对象,以添加或删除对象到数组。

-(void) addObject:(NSObject *)object toPoolOfObjects:(NSMutableDictionary*) objects 
{ 
    Class objectClass = [object class]; 
    @synchronized (objects) 
    { 
     NSMutableArray* objectArray = [objects objectForKey:objectClass]; 

     if(objectArray == nil) 
     { 
      objectArray = [[[NSMutableArray alloc] init] autorelease]; 
      [objects setObject:objectArray forKey:objectClass]; 
     } 
     [objectArray addObject:object]; 
    } 

} 
+4

是不是锁定点*不*要做到这一点? – omz

+2

顺便说一句,当你在任何地方使用它时,@synchronized指令只有一个效果。它不会阻止你访问@synchronized块之外的对象,所以你可以*访问'无论你喜欢的对象',但你真的不应该这样做。 – omz

+0

嗯,我正在尝试做类似于脏读和类似于数据库的非重复读取:http://en.wikipedia.org/wiki/Isolation_(database_systems)#Dirty_readsI需要同步某些代码块,这些代码块需要保持一致,但在第一种方法中,因为我只需要读取数据,并且不介意它是否不一致,所以我需要一种方法来实现这一点。第一种方法不应该被锁定对象的其他方法的锁定操作阻止,因为我需要第一种方法是快速的。如果其他方法由于锁定而变慢,那没问题。 – xcoder

回答

0

使用替代语言的@synchronize方法或等价的:

  • 如果您的实例是从多个线程访问,这是不是一成不变,你将需要大约访问状态的所有方法同步块是可以被突变
    • 您的对象是不可变如果没有访问器/方法更改对象的内部状态。

使用的是标准的NSMutableArray /的NSMutableDictionary原语的状态,但这些都不是线程安全的,因此跨线程共享时需要锁。在不知道您的API及其消费者的访问与更新频率的情况下,很难推荐特定的解决方案。

如果您的API主要是读取,您可以逃脱以下解决方案,它实现了写入时的副本。尽管一如既往,您必须确定解决方案是否满足您的性能要求。

- (NSArray *)getActiveObjectsOfType:(Class)objectClass { 
    @synchronize(self.activeObjects) { 
     return [self.activeObjects objectForKey:objectClass]; 
    } 
} 

- (void)addObject:(NSObject *)object { 
    Class objectClass = [object class]; 

    // synchronize access to activeObjects 
    @synchronize(self.activeObjects) { 
     NSArray *existingArray = [[[self.activeObjects objectForKey:objectClass] retain] autorelease]; 

     NSMutableArray *newArray; 
     if (existingArray) { 
      newArray = [NSMutableArray arrayWithArray:existingArray]; 
     } else { 
      newArray = [NSMutableArray array]; 
     } 

     [newArray addObject:object]; 

     [self.activeObjects setObject:newArray forKey:objectClass]; 
    } 
} 

什么是重要的这种解决方案需要注意的是getActiveObjectsOfType返回NSArray的是不可改变的。

+0

为了完全安全,我认为你需要将第一个' existingArray'与[[[retain] autorelease];'。请参阅http://developer.apple。com/library/mac/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#// apple_ref/doc/uid/10000057i-CH8-SW8 – NSGod

+0

是的,你是对的。当我们退出第一个同步块时,另一个线程(调用'addObject:')可以释放第二个'@ synchronize'块中的'existingArray'。 –

+0

我看到你的建议可能会解决我最初的问题,但也会创建另一个 - 看起来可能的是,如果两个线程调用addObject,取决于线程的执行顺序,添加的一个对象可能会“丢失”,因为可以在一个线程添加对象之前进行复制。之后,另一个线程将添加自己的对象,然后替换第二个同步块中的数组。当另一个线程替换第二个同步块中的数组时,在另一个线程中添加的对象(但不会被复制)将会丢失。 – xcoder

相关问题