Подтвердить что ты не робот

Как использовать NSConditionLock? Или NSCondition

Я пытаюсь заставить одну функцию ждать другого, и я хотел бы использовать NSCondionLock для этого. Я не прошу о помощи, но действительно надеюсь, что кто-то может показать мне приличный учебник или пример, чтобы объяснить NSConditionLock, или, возможно, предложить лучший метод.

4b9b3361

Ответ 1

EDIT:, как прокомментировал @Bonshington, этот ответ относится к NSCondition (в отличие от NSConditionLock):

- (void) method1 {

    [myCondition lock];
    while (!someCheckIsTrue)
        [myCondition wait];


    // Do something.


    [myCondition unlock];
}

- (void) method2 {

    [myCondition lock];


    // Do something.


    someCheckIsTrue = YES;
    [myCondition signal];
    [myCondition unlock];
}

someCheckIsTrue может быть любым, это может быть простая переменная BOOL или даже что-то вроде [myArray count] == 0 && color == kColorRed, это не имеет значения. Дело только в том, что в одном методе вы проверяете условие, когда у вас есть блокировка, а в другом методе вы вносите изменения, которые могут привести к тому, что условие станет истинным и при блокировке. Магия - это часть wait и signal: wait фактически разблокирует блокировку и снова получает ее после некоторого другого потока, называемого signal.

Ответ 2

Для тех, кто хочет получить образец тестового класса, я публикую то, что я сделал, чтобы поиграть и понять, как работает NSCondition.

// --- MyTestClass.h File --- //
@interface MyTestClass

- (void)startTest;

@end

// --- MyTestClass.m File --- //
@implementation MyTestClass
{
    NSCondition *_myCondition;
    BOOL _someCheckIsTrue;
}

- (id)init
{
    self = [super init];
    if (self) 
    {
        _someCheckIsTrue = NO;
        _myCondition = [[NSCondition alloc] init];
    }
    return self;
}

#pragma mark Public Methods

- (void)startTest
{
    [self performSelectorInBackground:@selector(_method1) withObject:nil];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        sleep(5);
        [self performSelectorInBackground:@selector(_method2) withObject:nil];
    });
}

#pragma mark Private Methods

- (void)_method1
{
    NSLog(@"STARTING METHOD 1");

    NSLog(@"WILL LOCK METHOD 1");
    [_myCondition lock];
    NSLog(@"DID LOCK METHOD 1");

    while (!_someCheckIsTrue)
    {
        NSLog(@"WILL WAIT METHOD 1");
        [_myCondition wait];
        NSLog(@"DID WAIT METHOD 1");
    }

    NSLog(@"WILL UNLOCK METHOD 1");
    [_myCondition unlock];
    NSLog(@"DID UNLOCK METHOD 1");

    NSLog(@"ENDING METHOD 1");
}

- (void)_method2
{
    NSLog(@"STARTING METHOD 2");

    NSLog(@"WILL LOCK METHOD 2");
    [_myCondition lock];
    NSLog(@"DID LOCK METHOD 2");

    _someCheckIsTrue = YES;

    NSLog(@"WILL SIGNAL METHOD 2");
    [_myCondition signal];
    NSLog(@"DID SIGNAL METHOD 2");

    NSLog(@"WILL UNLOCK METHOD 2");
    [_myCondition unlock];
    NSLog(@"DID UNLOCK METHOD 2");
}

@end


// --- Output --- //
/*
2012-11-14 11:01:21.416 MyApp[8375:3907] STARTING METHOD 1
2012-11-14 11:01:21.418 MyApp[8375:3907] WILL LOCK METHOD 1
2012-11-14 11:01:21.419 MyApp[8375:3907] DID LOCK METHOD 1
2012-11-14 11:01:21.421 MyApp[8375:3907] WILL WAIT METHOD 1
2012-11-14 11:01:26.418 MyApp[8375:4807] STARTING METHOD 2
2012-11-14 11:01:26.419 MyApp[8375:4807] WILL LOCK METHOD 2
2012-11-14 11:01:26.419 MyApp[8375:4807] DID LOCK METHOD 2
2012-11-14 11:01:26.420 MyApp[8375:4807] WILL SIGNAL METHOD 2
2012-11-14 11:01:26.420 MyApp[8375:4807] DID SIGNAL METHOD 2
2012-11-14 11:01:26.421 MyApp[8375:4807] WILL UNLOCK METHOD 2
2012-11-14 11:01:26.421 MyApp[8375:3907] DID WAIT METHOD 1
2012-11-14 11:01:26.421 MyApp[8375:4807] DID UNLOCK METHOD 2
2012-11-14 11:01:26.422 MyApp[8375:3907] WILL UNLOCK METHOD 1
2012-11-14 11:01:26.423 MyApp[8375:3907] DID UNLOCK METHOD 1
2012-11-14 11:01:26.423 MyApp[8375:3907] ENDING METHOD 1
*/

Ответ 3

NSConditionLock пример программы.

#import <Foundation/Foundation.h>

#define IDLE 0
#define START 1
#define TASK_1_FINISHED 2
#define TASK_2_FINISHED 3
#define CLEANUP_FINISHED 4

#define SHARED_DATA_LENGTH 1024 * 1024 * 1024

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:IDLE];
        char *shared_data = calloc(SHARED_DATA_LENGTH, sizeof(char));

        [NSThread detachNewThreadWithBlock:^{
            [lock lockWhenCondition:START];

            NSLog(@"[Thread-1]: Task 1 started...");
            for (size_t i = 0; i < SHARED_DATA_LENGTH; i++) {
                shared_data[i] = 0x00;
            }
            [lock unlockWithCondition:TASK_1_FINISHED];
        }];

        [NSThread detachNewThreadWithBlock:^{
            [lock lockWhenCondition:TASK_1_FINISHED];
            NSLog(@"[Thread-2]: Task 2 started...");
            for (size_t i = 0; i < SHARED_DATA_LENGTH; i++) {
                char c = shared_data[i];
                shared_data[i] = ~c;
            }
            [lock unlockWithCondition:TASK_2_FINISHED];
        }];

        [NSThread detachNewThreadWithBlock:^{
            [lock lockWhenCondition:TASK_2_FINISHED];

            NSLog(@"[Thread-3]: Cleaning up...");
            free(shared_data);
            [lock unlockWithCondition:CLEANUP_FINISHED];
        }];

        NSLog(@"[Thread-main]: Threads set up. Waiting for 2 task to finish");
        [lock unlockWithCondition:START];
        [lock lockWhenCondition:CLEANUP_FINISHED];
        NSLog(@"[Thread-main]: Completed");
    }
    return 0;
}