gpt4 book ai didi

objective-c - 如何在非 ARC 世界中使用 NSMutableDictionary 避免 EXC_BAD_ACCESS?

转载 作者:行者123 更新时间:2023-12-03 12:55:53 24 4
gpt4 key购买 nike

根据下面的代码,...

// Init a dictionary
NSMutableDictionary *dic = [NSMutableDictionary alloc] init];
[dic setObject:anObj forKey:@"key"]

...

// A : run on thread X
OBJ *obj = [dic objectForKey:@"key"];
[obj doSomething];

...

// B : run on thread Y
[dic removeObjectForKey:@"key"];

如果 A 和 B 在不同的线程 X 和 Y 上运行, EXC_BAD_ACCESS可以发生,对吧?
因为 :
  • -[NSDictionary objectForKey:]不保留和自动释放返回的值。
  • -[NSMutableDictionary removeObjectForKey:]确实释放对象。
  • [obj doSomething];如果 [dic removeObjectForKey:@"key"]; 会崩溃首先执行。

    弹出一个问题:

    How can we avoid this ?



    我的第一个想法是保留 -[NSDictionary objectForKey:] 的返回值,但这还不够。
    为什么 ?由于上述两个原因,返回值仅由字典保留的持续时间。如果 B 在这段时间内执行,它肯定会崩溃。
    // A : run on thread X
    OBJ *obj = [[[dic objectForKey:@"key"] retain] autorelease];
    [obj doSomething];

    ...

    // B : run on thread Y
    [dic removeObjectForKey:@"key"];

    所以,只保留是行不通的。 RIP 第一个想法

    第二个想法是序列化它们。
    // A : run on thread X
    @synchronized(dic) {
    OBJ *obj = [[dic objectForKey:@"key"] retain] autorelease];
    }
    [obj doSomething];

    ...

    // B : run on thread Y
    @synchronized(dic) {
    [dic removeObjectForKey:@"key"];
    }

    如果我这样做,它将正常工作。

    第三个想法是过度保留字典中的所有对象,并在从字典中删除或解除字典时释放它们。
    // Init a dictionary
    NSMutableDictionary *dic = [NSMutableDictionary alloc] init];
    [anObj retain];
    [dic setObject:anObj forKey:@"key"]

    ...

    // A : run on thread X
    OBJ *obj = [dic objectForKey:@"key"];
    [obj doSomething];

    ...

    // B : run on thread Y
    OBJ *obj = [dic objectForKey:@"key"];
    [dic removeObjectForKey:@"key"];
    [obj release];

    这是我的问题:
  • 非 ARC 世界的人们如何在不面对 EXC_BAD_ACCESS 的情况下使用 NSMutableDictionary ?
  • 他们总是使用单线程吗?
  • 他们是否总是像我上面演示的那样使用锁定或同步?
  • 而且,在ARC世界中,这种情况会发生吗?
  • 还是我的假设都是错误的?
  • 最佳答案

    NSMutableDictionary不是线程安全的。保留在 obj 上只是问题的一部分。即使您正在访问不同的元素,在单独的线程上阅读字典时也不能安全地对其进行变异。你可以得到垃圾。它不是线程安全的容器。这与 ARC 无关。

    这个问题有很多解决方案。在许多情况下,NSMutableDictionary无论如何都是错误的工具。使用小值对象可以更好地使用它。使用值对象允许您通过各种方式控制线程安全。

    通常最好的工具是 GCD。 Jano 在 Multi-threaded Objective-C accessors: GCD vs locks 中提供了一个很好的例子.我推荐值对象,但同样的技术可以用来包装 NSMutableDictionary如有必要。它允许并行读取和非阻塞写入,而不需要内核锁。它是高性能的并且不难实现。

    我成功使用的另一种技术是切换到不可变数据结构。使用 NSDictionary而不是 NSMutableDictionary .有两种方法可以做到这一点:

  • 存储可变字典,但将不可变副本传递给其他线程或调用者,或
  • 存储不可变字典。当您需要对其进行变异时,请改为替换它。

  • 对于不经常变异的合理大小的字典,这可能比您想象的要快得多,并且它使线程安全更加简单。请记住,复制不可变对象(immutable对象)几乎是免费的(它通常实现为保留)。

    关于objective-c - 如何在非 ARC 世界中使用 NSMutableDictionary 避免 EXC_BAD_ACCESS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23912029/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com