Общая память с «мьютексом» и NSCondition на iPhone

#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 приведены в таком порядке.
Кажется, этот код работает, когда я добавляю один объект в свой основной поток. Однако, когда я хочу добавить более одного, он блокируется вокруг блокировки.

РЕДАКТИРОВАТЬ Я попробовал что-то другое, но поведение было не таким, как ожидалось:
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];
}
таким образом, я разблокировал NSMutableArray, чтобы MainThread мог добавлять объекты.

Комментарии:

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  
  

Надеюсь, это может кому-то помочь!