Objective-C:在一个线程中分配并在另一个线程中释放

Posted

技术标签:

【中文标题】Objective-C:在一个线程中分配并在另一个线程中释放【英文标题】:Objective-C: Allocation in one thread and release in other 【发布时间】:2011-01-15 05:47:22 【问题描述】:

我在我的主线程中这样做:

CCAnimation *anim; //class variable

[NSThread detachNewThreadSelector:@selector(loadAimation) toTarget:self withObject:nil];

在加载动画中:

-(void) loadAnimation 
    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
        anim = [[CCAnimaton alloc] init];
        [autoreleasepool drain];

在主线程中我释放它:

        [anim release];

现在我想问一下关于内存管理是否可以。

【问题讨论】:

loadAimation 应该是loadAnimation 吗?为什么anim 是类变量而不是属性?发布的代码是什么?没有足够的信息来判断对象的创建和销毁是否平衡。 是的,你是对的,我想问题出在发布时确实发生了什么事,(我只是想问问这样做是否可以)。实际上它与发布前的 cocos2d 有关 我正在制作 CCAction 并且我有一个 CCSprite *sp,我只是在做 [sp runAction:anim];在动画运行时我正在释放它,虽然动画在视觉上没有任何变化,但它是对的吗? 这取决于一切是如何实现的。任何获得所有权的对象都将保留动画。如果对象没有取得所有权,它就不会保留动画。检查 cocos2d 文档的所有权规则。即便如此,您仍然可能遇到导致内存管理问题的race condition(例如,动画在拥有对象可以保留在另一个线程中之前在一个线程中释放)。 不,我的程序中没有竞争条件,但我的问题得到了解决。这段代码的概念很好,但正如你所指出的,不能有竞争条件。感谢您的回复。 【参考方案1】:

可以在一个线程中分配一个对象并在另一个线程中释放它。但是,根据您的处理方式,您的代码可能会出错。

如果可能的话,把anim 变成一个属性,这样你就不用太担心内存管理了。如果不能,可以应用访问器模式,但必须自己实现。

static CCAnimation *anim=nil;

+(CCAnimation*)anim 
    @synchronized(self) 
        return [[anim retain] autorelease];
    

+(void)setAnim:(CCAnimation*)animation 
    @synchronized(self) 
        if (anim != animation) 
            [anim release];
            anim = [animation retain];
        
    

-(void)loadAnimation 
    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
    [[self class] setAnim:[[[CCAnimaton alloc] init] autorelease]];
    [autoreleasepool drain];

【讨论】:

不要@synchronize(self) 来实现标准的setter/getter。使用@property() 和@synthesize。结果会更快,保证正确(不是上面说的不对,而是……为什么要写编译器可以给你写的代码呢?)。 @bbum:因为这些不是您的标准访问器,并且 anim 不是(实例)属性。注意方法前的+anim 是一个类属性,Apple 的编译器不会为您生成它(尽管它似乎支持它们的点语法)。在处理多线程时,getter 和 setter 中的@synchronize 是非常必要的。 德普。是的——对不起。错过了+。请注意,您的退货方式不正确;如果你希望它是适当的原子,它应该return [[anim retain] autorelease]; 以确保anim 在本地线程中的生命周期遵循正确的语义(实际上,@synthesize 将在实例情况下使用标准访问器执行)。 @bbum:这是为了防止一个线程使用存储的对象和另一个分配给它的线程之间的竞争条件?也就是说,线程 A 获取对象,然后线程 B 在 A 有机会保留它之前将其分配给该属性。感谢您的信息。 没错。非常微妙的竞争条件之一。【参考方案2】:

应该没问题,当然,如果您要保护对指针变量的访问。

【讨论】:

以上是关于Objective-C:在一个线程中分配并在另一个线程中释放的主要内容,如果未能解决你的问题,请参考以下文章

根据用户选择将 UIPickerView 中的数据保存在 NSUserDefaults 中,并在另一个 ViewController Objective-C 中调用

在一个线程中创建并在objective-C中传递给另一个线程的自动释放对象

如何检测按下的按钮并将其显示在另一个视图上? Objective-C

在一个线程中修改成员变量并在另一个线程中读取

BOOST 如何在一个线程中发送信号并在另一个线程中执行相应的插槽?

多线程堆管理