【问题标题】:Multithreading and autorelease pool多线程和自动释放池
【发布时间】:2011-02-13 10:56:19
【问题描述】:

当我通过 GCD 掌握多线程技术时,我遇到了一些问题。假设你有以下方法:

    - (void)method {
    NSString *string= [NSString string]; //will be autoreleased

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    //very very lengthy operation...

    NSLog(@"%@", string); //is it safe?
    });
}

我想知道这是否正确,因为我认为我应该在块执行之前保留字符串:实际上我担心事件循环完成并在块中使用 string 之前发送 string 自动释放消息.这会使程序崩溃。

我说的对吗?我应该向string 发送保留和释放消息还是这是正确的实现? 提前致谢!

【问题讨论】:

  • @yes123 你没有给出论据,扩展你的观点。
  • @yes123: 任何想要完成某事的人,任何想要完成某事的人 =)

标签: objective-c multithreading cocoa memory-management grand-central-dispatch


【解决方案1】:

我想知道这是否正确,因为我认为我应该在块执行之前保留字符串:实际上我担心事件循环完成并在块中使用字符串之前向字符串发送自动释放消息。

不要害怕:
块捕获周围方法/函数的范围,因为它会自动retains 块内使用的任何对象变量。请注意,当您在块内使用 self 时,这可能会极大地影响对象的生命周期!

这条规则有一个例外,那就是声明为的变量

__block SomeObjectPointerType variableName

更新

因为对这个答案有一个新的评论,我可能应该补充一点,随着 ARC 的引入,情况发生了一些变化:

在 ARC 下,所有对象变量默认为 __strong这也适用于标有 __block 的变量。如果你想避免在块中强捕获变量,你应该定义一个局部变量__weak

结束更新

如果您想了解有关块的更多信息,bbum 在 WWDC 2010 上举办了一场名为 Introducing Blocks and Grand Central Dispatch on iPhone 的精彩会议。

“区块详情”部分从 11:30 开始。

【讨论】:

  • 如果使用__block, NSLog(@"%@", bself.string);安全吗?
【解决方案2】:

担心的是;自动释放对象何时释放?

NSString *myString= [NSString stringWithFormat: @"%@", stringVariable];

myString 依赖于 stringVariable,只要 stringVariable 释放,myString 就会立即释放。

NSString *myString= [NSString stringWithString: @"stringVariable"];

在实践中观察到 myString 可能会在方法完成后立即释放。

现在,如果您更改代码并使用 NSAutoReleasePool

- (void)method {
    NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init];

    NSString *string= [NSString string]; //will be autoreleased

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    //very very lengthy operation...

    // string will be released here
    [pool release];

    NSLog(@"%@", string); // it is not safe?
    });
}

自动释放对象在它们所在的自动释放池释放或它们所依赖的对象释放时释放。

现在,如果您在线程中使用该方法,您应该在其中使用自动释放池。

- (void)method {
    NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init];

        // lengthy operations ...
    [pool release];
}

【讨论】:

  • -1 你的回答有不少错误: 1.没有[NSString stringVariable]这样的方法。 2.autorelease“在方法完成后”释放对象。当当前NSAutoreleasePool 耗尽时,它会释放对象。如果您自己没有指定一个,那将是事件循环管理的那个,所以对象lives until the end of the current iteration of the loop。 3.您需要拨打[pool drain]
  • "myString 依赖于 stringVariable,只要 stringVariable 释放,myString 就会立即释放。"那也是错误的! (如果这是真的,后果将至少有点灾难性...)+[NSString stringWithFormat:] 通过评估格式创建一个新的自动释放字符串,从而创建所有状态的快照用于替换占位符的参数。
  • 这个答案是如何获得支持的?即使经过编辑,它仍然包含有关字符串创建的严重错误信息。
  • 无意冒犯,但请查看我的第一条评论中关于自动释放池的链接。 (您也可以考虑阅读class reference for NSAutoreleasePool。)关于 NSString,再次:Read the docs! 要进一步参考块,您可能想观看我在答案中链接到的 WWDC 会话。
  • 人,谁在乎NSString的false方法?我们在这里讨论自动释放池。
猜你喜欢
  • 2011-11-19
  • 2014-09-02
  • 1970-01-01
  • 2020-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-16
  • 1970-01-01
相关资源
最近更新 更多