Имеет ли смысл делать atomic BOOL-флагом в многопоточном программировании? - PullRequest
5 голосов
/ 16 декабря 2010

Я довольно новичок в многопоточном программировании и задаюсь вопросом, нормально ли это или создать свойство типа

@property BOOL shouldDoIt; //atomic

, который будет использоваться в цикле, который вызывается в фоновом режиме

- (void) loop{
    // ... do stuff ...
    if (self.shouldDoIt) {
        [self doIt];
        self.shouldDoIt = NO;
    }
    // ... do more stuff ...
}

и изменено в методе, вызываемом из основного потока

- (void) methodCalledFromMainThread{
    self.shouldDoIt = YES;
}

У меня есть , чтобы сделать его атомарным или это ничего не меняет? Я знаю, что атомарный медленнее по сравнению с неатомарным, и моей программе нужна большая скорость, но если не использовать атомарный, тогда выполнение if (shouldDoIt){ может дать сбой?

Ответы [ 4 ]

2 голосов
/ 16 декабря 2010

Ответ полностью зависит от ответа на вопрос:

«вам нужно запускать doIt ровно один раз для каждого раза, когда основной поток устанавливает флаг shouldDoIt?»

Если ответ на этот вопрос «да», то ваш код не будет работать, потому что основной поток может установить shouldDoIt на YES после того, как вы запустили doIt, но до того, как вы сбросили флаг.

Если ответ «нет», то в этом узком случае у вас есть что-то вроде ОК, за исключением того факта, что в конфигурации с несколькими ЦП флаг может кэшироваться таким образом, что другой поток делаетне сразу вижу изменения.Таким образом, вы, по крайней мере, хотите использовать OSAtomicTestAndClearBarrier () и OSAtomicTestAndSetBarrier (), которые имеют низкий уровень, следовательно, настолько быстрый, насколько вы можете получить.

Однако я скептически отношусь к тому, что вам нужносделать это.Я думаю, вы могли бы найти, что рефакторинг дизайна каким-то образом даст лучшие результаты в зависимости от того, что вы пытаетесь сделать в doIt, do stuff и do more stuff.

2 голосов
/ 16 декабря 2010

На майском потоке у вас есть BOOL, для которого вы хотите установить значение no после выполнения некоторой работы в обратном потоке

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


-(void) backThreadAction:(id*)someObject{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    //do stuff here

    [self performSelectorOnMainThread:@selector(didFinishBackThreadAction:) withObject:nil waitUntilDone:NO];
    [pool release];
}

-(void) didFinishBackThreadAction:(id *)someObject{
   //set your bool to no
}
0 голосов
/ 16 декабря 2010

в этой части кода:

if (self.shouldDoIt) {
    [self doIt];

shouldDoIt, будучи атомарным, не гарантирует, что оно все равно true, когда вы вызываете doIt. Вы должны использовать блокировку, чтобы убедиться, что значение не изменилось после теста и до того, как вы действительно сделаете то, что должны сделать.

0 голосов
/ 16 декабря 2010

Прочтите сначала Руководство по программированию потоков от Apple, и я думаю, что вам нужен NSLock , но будьте осторожны, вы можете зайти в тупик.Удачи

...