Multithreading and autorelease pool
As I'm mastering my skills with multithreading with GCD, I've come across some question. Suppose you have the following method:
- (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?
});
}
I'm wondering if this is correct, because I think I should 开发者_StackOverflowhave retained string before the block execution: in fact I fear that the event loop finishes and sends string
an autorelease message before using string
in the block. That would crash the program.
Am I right? Should I send a retain and a release message to string
or this is the correct implementation?
Thanks in advance!
I'm wondering if this is correct, because I think I should have retained string before the block execution: in fact I fear that the event loop finishes and sends string an autorelease message before using string in the block.
Fear not:
A block captures the scope of the surrounding method/function in that it automatically retain
s any object-variable that is used inside of the block. Be aware of that when you use self
inside of a block, as this may greatly affect the lifetime of the object!
There is one exception to this rule, and that are variables declared as
__block SomeObjectPointerType variableName
Update
Because there’s a new comment on this answer, I should probably add that things changed a little with the introduction of ARC:
Under ARC all object variables default to __strong
, and this holds for variables marked with __block
as well. If you want to avoid strong capturing of a variable in a block, you should define a local variable that is __weak
.
End Update
If you like to learn more about blocks, bbum gave an excellent session called Introducing Blocks and Grand Central Dispatch on iPhone at WWDC 2010.
The "Block Details" section starts at 11:30.
The concern is; when an autorelease object releases?
NSString *myString= [NSString stringWithFormat: @"%@", stringVariable];
The myString depends upon stringVariable, whenever stringVariable releases the myString immediately releases.
NSString *myString= [NSString stringWithString: @"stringVariable"];
In practice it is observed the myString might be releases just after the completion of the method.
Now if you change your code and use 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?
});
}
The autorelease objects released when the auto release pool releases in which they exists or when the object releases on which they depends.
Now if you are using the method in a thread you should use auto release pool inside it.
- (void)method {
NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init];
// lengthy operations ...
[pool release];
}
精彩评论