ios - 集合在枚举时发生了变化——所有内容都是同步的,并且在迭代时没有发生变化

标签 ios objective-c synchronization iteration

我不是 Objective C 专家,问题出现在我没有编写的代码中。 但是,我进行了一项研究,但找不到可能是我的问题的根本原因。 (我对 Java 和 C/C++ 的多线程编程有很好的理解)。

下面是抛出异常(以崩溃结束)的代码的 [模糊] 版本:

@interface someInterface ()
@property (nonatomic) NSMutableArray *activeTokens;

下面的函数抛出异常:

@implementation someInterface

- (void)foo:(NSURL*)url headers:(NSDictionary*)headers
{
    @synchronized (self.activeTokens) {
        for (NSValue *object in self.activeTokens) {
            X *tokenObject = object.nonretainedObjectValue;
            if (tokenObject && [tokenObject.a.b isEqualToString:url.absoluteString]) {
                tokenObject.x = [headers objectForKey:@"somekey"];
                break;
            }
        }
    }
}

访问集合的附加函数:

- (X*)bar:(NSURL*)url protocol:(NSString*)str 
{


    X *token = [[X alloc] ...];
    @synchronized (_activeTokens){
        if (!_activeTokens) {
            _activeTokens = [[NSMutableArray alloc] init];
        }
        NSValue *value = [NSValue valueWithNonretainedObject:token];
        [_activeTokens addObject:value];
    }

    ...
}


- (void)releaseToken:(X*)token
{
    NSValue *value = [NSValue valueWithNonretainedObject:token];
    @synchronized(_activeTokens) {
        [_activeTokens removeObject:value];
    }
}



- (X*)getRequestToken:(R*)request
{
    @synchronized (self.activeTokens) {
        for (NSValue *object in self.activeTokens) {
            X *tokenObject = object.nonretainedObjectValue;
            if (tokenObject && [tokenObject.a isEqualToString:[request.headers objectForKey:@"someKey"]]) {
                return tokenObject;
            }
        }
    }
    return nil;
}

- (void)foooo:(BOOL)success reason:(NSString *)reason
{

    if (!success)
    {
        @synchronized (self.activeTokens) {
            for (NSValue *object in self.activeTokens) {
                X *tokenObject = object.nonretainedObjectValue;
                [tokenObject.s setR:reason];
            }
        }
    }
}

我唯一能想到的是同步时 activeToken 为 nil 的情况 - 但我认为这应该不是问题,不是吗?

更新: 经过调查和评论中的讨论,我认为唯一的情况是对象仍然为 nil,因此不会发生同步。

这里是苹果同步的实现:

BREAKPOINT_FUNCTION(
    void objc_sync_nil(void)
);


// Begin synchronizing on 'obj'. 
// Allocates recursive mutex associated with 'obj' if needed.
// Returns OBJC_SYNC_SUCCESS once lock is acquired.  
int objc_sync_enter(id obj)
{
    int result = OBJC_SYNC_SUCCESS;

    if (obj) {
        SyncData* data = id2data(obj, ACQUIRE);
        require_action_string(data != NULL, done, result = OBJC_SYNC_NOT_INITIALIZED, "id2data failed");

        result = recursive_mutex_lock(&data->mutex);
        require_noerr_string(result, done, "mutex_lock failed");
    } else {
        // @synchronized(nil) does nothing
        if (DebugNilSync) {
            _objc_inform("NIL SYNC DEBUG: @synchronized(nil); set a breakpoint on objc_sync_nil to debug");
        }
        objc_sync_nil();
    }

done: 
    return result;
}

我们可以看到在 nil 上同步时没有任何反应。

我会将数组的分配移动到初始化程序。

最佳答案

“强力”解决方案是使用++ 方法进行迭代,即:

for (NSInteger i = 0; i < self.activeTokens.count; i++)
  {
  NSValue *object = [self.activeTokens objectAtIndex:i];
  //...
  }

关于ios - 集合在枚举时发生了变化——所有内容都是同步的,并且在迭代时没有发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45547800/

相关文章:

android - 我可以使用 QT Creator 在 Windows 10 机器上同时为 Android 和 iOS 开发吗?

ios - 事件发生时更改特定 UITableViewCell 的 UIImage

objective-c - 导航栏和标签栏之间留有 50% 高度的 subview

JSF并发问题

没有同步的 Java 多线程行为

ios - 使用 AFNetworking 解析 JSON 文件

ios - 栏按钮项目无法执行操作 Swift

ios - typedef 枚举与 CGSize?

objective-c - 使用 objective-c 的 Web 应用程序编程?

c++ - 从 Qt 中的多个线程绘制