#iphone #multithreading #singleton #semaphore #shared-memory
#iPhone #многопоточность #синглтон #семафор #разделяемая память
Вопрос:
Что мне нужно сделать: Чтобы избежать глобальной переменной, у меня есть одноэлементный класс, содержащий массив. К этому массиву будут обращаться два разных потока :
— 1) первый будет основным потоком и должен будет время от времени добавлять объекты в этот NSMutableArray.
— 2) другой поток выполняет цикл (при значении TRUE) и пытается очистить массив (если он что-то содержит)
Моя идея заключалась (и что я делал до сих пор): в моем одноэлементном классе у меня есть NSMutableArray ( list
) и NSCondition ( conditionLock
).
Что делает мой основной поток, так это :
[[sharedSingleton conditionLock] lock];
[[sharedSingleton list] addObject:obj];
[[sharedSingleton conditionLock] signal];
[[sharedSingleton conditionLock] unlock];
Я хочу заблокировать объект, чтобы он не становился пустым, когда я пытаюсь поместить в него объекты. (защита общей памяти). Как только объект помещен в массив, я посылаю сигнал другому потоку. Если я правильно понял, это своего рода увеличение счетчика, как при использовании семафора, верно? Сигнал сообщает другому потоку «есть объект, продолжайте».
Что делает второй поток:
while (YES) {
[[sharedRequest conditionLock] lock];
[[sharedRequest conditionLock] wait];
RequestLauncher * req = [[RequestLauncher alloc] initWithGenericsObject:[[sharedRequest list] objectAtIndex:0]];
[req performSelectorOnMainThread:@selector(Launch)
withObject: nil
waitUntilDone:YES];
[[sharedRequest list] removeObjectAtIndex:0];
[[sharedRequest conditionLock] unlock];
}
Итак, я предполагаю, что моя проблема в том, что я блокирую, а затем жду сигнала, но все примеры Apple приведены в таком порядке.
Кажется, этот код работает, когда я добавляю один объект в свой основной поток. Однако, когда я хочу добавить более одного, он блокируется вокруг блокировки.
РЕДАКТИРОВАТЬ Я попробовал что-то другое, но поведение было не таким, как ожидалось:
таким образом, я разблокировал NSMutableArray, чтобы MainThread мог добавлять объекты.
while (YES) {
[[sharedRequest conditionLock] lock];
[[sharedRequest conditionLock] wait];
GenericsObject * obj = [[sharedRequest list] objectAtIndex:0];
[[sharedRequest list] removeObjectAtIndex:0];
[[sharedRequest conditionLock] unlock];
RequestLauncher * req = [[RequestLauncher alloc] initWithGenericsObject:obj];
[req performSelectorOnMainThread:@selector(Launch) withObject: nil waitUntilDone:YES];
}
Комментарии:
1. Привет, просто наблюдение, наличие второго потока, единственной целью которого является вызов селектора в главном потоке и ожидание, пока это не будет сделано, в некотором роде сводит на нет цель создания второго потока.
2. Вы абсолютно правы. Вот почему я сейчас использую NSOperation.. У меня только что возникла проблема с запуском асинхронного NSURLConnection не в основном потоке.
Ответ №1:
Второй поток вызывает метод в основном потоке и ожидает, пока не завершится выполнение метода в блокировке условий. Это привело бы к ВЗАИМОБЛОКИРОВКЕ. RequestLauncher не может быть вызван во втором потоке?
Комментарии:
1. Ну, я вызываю этот метод в главном потоке, потому что это асинхронный запрос, и для него нужен цикл выполнения, доступный только в главном потоке. Я «жду, пока не будет готово», чтобы одновременно устанавливалось только одно соединение. Вам нравится код, кроме этого? Что я мог тогда сделать?
Ответ №2:
Я, наконец, получил ответ.
Я больше привык к многозадачности C, объясняя здесь путаницу!
В принципе, код был почти хорош. Я думал, что signal увеличивает значение «семафора», чтобы, если один поток подавал сигнал 5 раз, другой поток также передавал условие ожидания 5 раз. Совсем нет.
Мой код в первом потоке был хорошим (т. е.)
[[sharedSingleton conditionLock] lock];
[[sharedSingleton list] addObject:obj];
[[sharedSingleton conditionLock] signal];
[[sharedSingleton conditionLock] unlock];
Следуя примеру Apple на этой странице, на этой странице , вот что я сделал
[[sharedRequest conditionLock] lock];
while ( ! ([[sharedRequest list] count] >0) ) {
[[sharedRequest conditionLock] wait];
}
GenericObjects * obj = [[sharedRequest list] objectAtIndex:0];
[[sharedRequest list] removeObjectAtIndex:0];
[[sharedRequest conditionLock] unlock];
RequestLauncher * req = [[RequestLauncher alloc] initWithGenericsObject:obj];
[[appDel queue] addOperation:req]; // appDel is an instance of the application delegate, and where queue is an instance of NSOperationQueue
Надеюсь, это может кому-то помочь!