Objective-C: 如何安全地修改不同线程中的 NSMutableArray?
Objective-C: How do I modify the NSMutableArray in a different thread safely?
我声明了一个原子 NSMutableArray 来保存对象
@property (atomic, strong) NSMutableArray *list;
@synthesize list;
然后我使用线程来保存对象,例如:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ // writing files into the disk in background
// do something..
[weakSelf.list addObject:object]; // add object at the end of the list
if (!weakSelf.threadCreateFlag) {
NSInvocationOperation *newoperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(createThreadMethod) object:nil]; // create thread to remove from the array
[weakSelf.serailQueue addOperation:newoperation];
}
});
我正在尝试读取索引 0 处的对象并将其从数组中删除
- (void)createThreadMethod {
self.threadCreateFlag = YES;
do {
NSLog(@"loop");
@autoreleasepool {
NSDictionary *object = (NSDictionary *)[self.list objectAtIndex:0];
[self.list removeObjectAtIndex:0];
// doing something...
}
} while(self.list.count > 0);
self.photoSavingLock = NO;
}
我遇到一个问题 - 有时,数组包含对象 0x0,我的应用程序会崩溃。
我对此做了一些研究,我认为是因为 removeObjectAtIndex
不是线程安全的。所以我试图在 read/remove 周围添加一个全局 @property (atomic, strong) NSLock *lock
并添加功能。
但是这次我得到了[NSLock deadlock]
.
使这个场景线程安全的正确方法是什么?
使事物线程安全的最简单的两种方法是使用@synchronized 或将事物分派到串行队列。
我的最高效率策略:拥有一个可变数组和一个不可变数组。当你想修改数组时:
- (void)modifyArray {
@synchronized (self) {
if (_mutableArray == nil) {
_mutableArray = [(_immutableArray ?: @[]) mutableCopy];
_immutableArray = nil;
}
// Modify the mutable array.
}
}
- (NSArray*)immutableArray {
@synchronized (self) {
if (_mutableArray != nil) {
_immutableArray = [_mutableArray copy];
_mutableArray = nil;
}
return _immutableArray;
}
}
显然你会得到 immutableArray一次,有一个擦除列表的调用,然后遍历 immutableArray。或者有一个方法 - (NSDictionary*)removeFirstElement 删除第一个元素, returns nil 如果没有其他要删除的元素。
我声明了一个原子 NSMutableArray 来保存对象
@property (atomic, strong) NSMutableArray *list;
@synthesize list;
然后我使用线程来保存对象,例如:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ // writing files into the disk in background
// do something..
[weakSelf.list addObject:object]; // add object at the end of the list
if (!weakSelf.threadCreateFlag) {
NSInvocationOperation *newoperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(createThreadMethod) object:nil]; // create thread to remove from the array
[weakSelf.serailQueue addOperation:newoperation];
}
});
我正在尝试读取索引 0 处的对象并将其从数组中删除
- (void)createThreadMethod {
self.threadCreateFlag = YES;
do {
NSLog(@"loop");
@autoreleasepool {
NSDictionary *object = (NSDictionary *)[self.list objectAtIndex:0];
[self.list removeObjectAtIndex:0];
// doing something...
}
} while(self.list.count > 0);
self.photoSavingLock = NO;
}
我遇到一个问题 - 有时,数组包含对象 0x0,我的应用程序会崩溃。
我对此做了一些研究,我认为是因为 removeObjectAtIndex
不是线程安全的。所以我试图在 read/remove 周围添加一个全局 @property (atomic, strong) NSLock *lock
并添加功能。
但是这次我得到了[NSLock deadlock]
.
使这个场景线程安全的正确方法是什么?
使事物线程安全的最简单的两种方法是使用@synchronized 或将事物分派到串行队列。
我的最高效率策略:拥有一个可变数组和一个不可变数组。当你想修改数组时:
- (void)modifyArray {
@synchronized (self) {
if (_mutableArray == nil) {
_mutableArray = [(_immutableArray ?: @[]) mutableCopy];
_immutableArray = nil;
}
// Modify the mutable array.
}
}
- (NSArray*)immutableArray {
@synchronized (self) {
if (_mutableArray != nil) {
_immutableArray = [_mutableArray copy];
_mutableArray = nil;
}
return _immutableArray;
}
}
显然你会得到 immutableArray一次,有一个擦除列表的调用,然后遍历 immutableArray。或者有一个方法 - (NSDictionary*)removeFirstElement 删除第一个元素, returns nil 如果没有其他要删除的元素。