属性,线程,内存管理和Rock&滚

时间:2014-05-01 17:04:41

标签: ios objective-c multithreading memory-management

环境:Mac OS X 10.9,Xcode 5.0.2,ARC禁用。

问题:所有线程完成工作后如何释放属性的空闲内存。见下面的例子。

我用一个按钮创建迷你示例“(IBAction)btnRun:(id)sender”。 示例读取txt文件并填写NSArray属性(sharedListWords)。然后运行两个线程,每个线程显示单词,
参见 OUT Section 。当线程完成一个作业时,属性(self.sharedListWords)没有被释放!但是我想要为(self.sharedListWords)属性分配的空闲内存。动作“btnRun”在线程完成作业之前退出,我不能在此动作中释放(self.sharedListWords)。

线程完成作业后属性(self.sharedListWords)的可用内存是多少?是好的答案here通过创建依赖操作jobFinished(),但是如何正确释放属性?

这是我在Objective-c上的第一个多线程程序,我很乐意进行调整。


AppDelegate.h:

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate>
{
    volatile int32_t sharedIndex;   // Shared between threads, current index in array
    NSOperationQueue* operationQueue;
}
@property (assign) IBOutlet NSWindow *window;
// Shared between threads, list of words
@property (atomic, retain) NSArray* sharedListWords;
- (void)worker;

@end

AppDelegate.m:

#import "AppDelegate.h"

@implementation AppDelegate

- (IBAction)btnRun:(id)sender
{
    // Read txt file dictionary of words, where is each words in new line.
    NSString* dictionaryFilePath = [NSString stringWithFormat:@"/Users/admin/dictionary.txt"];
    NSString* fileContents = [NSString stringWithContentsOfFile:dictionaryFilePath
                                                       encoding:NSUTF8StringEncoding error:nil];
    // Get array of string separated by new line
    self.sharedListWords = [fileContents componentsSeparatedByCharactersInSet:
                                [NSCharacterSet newlineCharacterSet]];

    //self.sharedListWords = @[@"one",@"two",@"three",@"four",@"five",@"six",@"seven",@"eight",@"nine",@"ten"];

    self->sharedIndex = -1;

    int numberOfThreads = 2;

    // Run method working() in separate threads
    for(int i=0; i<numberOfThreads; ++i)
    {
        //////////////////////////////////////////
        // Create a thread
        // Create new NSOperatin object with function puting in @selector() for run in other thread.
        NSOperation* startBruteOper = [[NSInvocationOperation alloc]
                                       initWithTarget:self selector:@selector(worker) object:nil];
        // Add the operation to the queue and let it to be executed.
        [operationQueue addOperation:startBruteOper];
        [startBruteOper release];
        /////////////////////////////////////////
    }
}

- (void)worker
{
    unsigned long countWords = [self.sharedListWords count];

    int32_t index = 0;

    // Use atomic operation for thread safe
    while( (index = OSAtomicIncrement32( &(self->sharedIndex) ) ) < countWords )
    {
        NSLog(@"[%@] working on \"%@\"",
              [NSThread currentThread],
              [self.sharedListWords objectAtIndex:index]);
    }

    NSLog(@"[%@] work is finish.", [NSThread currentThread]);
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Multithreading queue list
    operationQueue = [[NSOperationQueue alloc] init];
}

@end

OUT部分

[<NSThread: num = 2}] working on "one"
[<NSThread: num = 3}] working on "two"
[<NSThread: num = 2}] working on "three"
[<NSThread: num = 3}] working on "four"
[<NSThread: num = 2}] working on "five"
[<NSThread: num = 3}] working on "six"
[<NSThread: num = 2}] working on "seven"
[<NSThread: num = 3}] working on "eight"
[<NSThread: num = 2}] working on "nine"
[<NSThread: num = 3}] working on "ten"
[<NSThread: num = 2}] work is finish.
[<NSThread: num = 3}] work is finish.

2 个答案:

答案 0 :(得分:2)

这是马丁斯指示后的正确代码。

AppDelegate.h:

    #import <Cocoa/Cocoa.h>

    @interface AppDelegate : NSObject <NSApplicationDelegate>
    {
        volatile int32_t sharedIndex;   // Shared between threads, current index in array
        NSOperationQueue* operationQueue;
    }
    @property (assign) IBOutlet NSWindow *window;
    // Shared between threads, list of words
    @property (atomic, retain) NSArray* sharedListWords;
    - (void)worker;

    @end

AppDelegate.m:

    #import "AppDelegate.h"

    @implementation AppDelegate

    - (IBAction)btnRun:(id)sender
    {
        // Read txt file dictionary of words, where is each words in new line.
        NSString* dictionaryFilePath = [NSString stringWithFormat:@"/Users/admin/dictionary.txt"];
        NSString* fileContents = [NSString stringWithContentsOfFile:dictionaryFilePath
                                                           encoding:NSUTF8StringEncoding error:nil];
        // Get array of string separated by new line
        self.sharedListWords = [fileContents componentsSeparatedByCharactersInSet:
                                    [NSCharacterSet newlineCharacterSet]];

        //self.sharedListWords = @[@"one",@"two",@"three",@"four",@"five",@"six",@"seven",@"eight",@"nine",@"ten"];

        self->sharedIndex = -1;

        int numberOfThreads = 2;

        NSOperation* jobFinishedOper = [[NSInvocationOperation alloc]
                                    initWithTarget:self selector:@selector(jobFinished) object:nil];

        // Run method working() in separate threads
        for(int i=0; i<numberOfThreads; ++i)
        {
            //////////////////////////////////////////
            // Create a thread
            // Create new NSOperatin object with function puting in @selector() for run in other thread.
            NSOperation* startBruteOper = [[NSInvocationOperation alloc]
                                           initWithTarget:self selector:@selector(worker) object:nil];
            // Add the operation to the queue and let it to be executed.
            [operationQueue addOperation:startBruteOper];
            [jobFinishedOper addDependency:startBruteOper]; // 'jobFinishedOper' run only when 'startBruteOper' finished!
            [startBruteOper release];
            /////////////////////////////////////////
        }
        // 'jobFinishedOper' run only when all prevous operation is finished!
        [operationQueue addOperation:jobFinishedOper];
        [jobFinishedOper release];
    }

    - (void)worker
    {
        unsigned long countWords = [self.sharedListWords count];

        int32_t index = 0;

        // Use atomic operation for thread safe
        while( (index = OSAtomicIncrement32( &(self->sharedIndex) ) ) < countWords )
        {
            NSLog(@"[%@] working on \"%@\"",
                  [NSThread currentThread],
                  [self.sharedListWords objectAtIndex:index]);
        }

        NSLog(@"[%@] work is finish.", [NSThread currentThread]);
    }

    - (void)jobFinished
    {
        self.sharedListWords = nil;
    }

    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
    {
        // Multithreading queue list
        operationQueue = [[NSOperationQueue alloc] init];
    }

    @end

答案 1 :(得分:1)

您可以在所有&#34; worker&#34;上添加依赖的其他操作。操作,如 在

中描述

该操作在所有依赖项完成后运行,因此您可以调用

self.sharedListWords = nil;

在完成的操作中释放数组。