Как безопасно заполнить массив из одного потока, читая его в другом в Objective-C? - PullRequest
2 голосов
/ 07 июня 2009

Во-первых, я не очень знаком с использованием потоков, и я учусь на лету. У меня есть массив, который используется в потоке а и заполняется в потоке б. Что я хочу сделать, так это найти лучший способ ожидания массива из потока b, прежде чем использовать его в потоке a.

Ответы [ 3 ]

4 голосов
/ 08 июня 2009

Вы можете скопировать массив в потоке чтения, чтобы он не изменялся во время чтения, или вы можете @synchronize получить доступ к массиву:

- (void) writer
{
    @synchronized(theArray)
    {
        [theArray addObject:foo];
    }
}

- (void) reader
{
    @synchronized(theArray)
    {
        for (id item in theArray)
            [item …];
    }
}
2 голосов
/ 07 июня 2009

Я не использовал Objective C, но вы ищете блокировку условий. Это тип блокировки (мьютекс), который препятствует доступу потоков к заблокированным данным, но сохраняет очередь всех потоков, которые запросили разрешение (часто с использованием семафора). Когда данные разблокируются, блокировка условия автоматически активирует запрашивающие потоки.

В вашем случае массив будет заблокирован потоком B во время его заполнения. Когда поток A пытается получить доступ к массиву, он выдаст, потому что поток B в настоящее время удерживает блокировку. По завершении потока B он увидит, что поток A попытался получить доступ к массиву, пока он был заблокирован, и активировать поток A. Затем поток A может безопасно получить доступ к массиву.

Вот первый результат после поиска в Google блокировок условий в Objective C. Он касается API для iPhone, но, тем не менее, может быть полезным:

http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW4

1 голос
/ 08 июня 2009

Ответ зависит в некоторой степени от того, что вы делаете с содержимым массива.

В некоторой степени вопрос не имеет большого смысла - если поток a должен ждать, пока весь массив не будет заполнен в потоке b, то почему бы просто не выполнить заполнение в потоке a? Что еще он делает во время ожидания массива?

В качестве альтернативы, если поток a может продвигаться вперед по мере получения каждого элемента массива, тогда может иметь больше смысла передавать каждую полученную запись массива из потока b в поток a по мере их создания. В этом случае у вас фактически есть очередь, которая является общим шаблоном производителя / потребителя для многопоточной работы - поток b заполняет очередь, из которой поток читает данные.

См. Раздел «Использование объекта NSConditionLock» ссылки, которую Кай опубликовал для примера блокировки производителя / потребителя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...