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

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

EDIT Я пробовал что-то другое, но поведение было не таким, как ожидалось:
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 мог добавлять объекты.


person Pierre    schedule 07.05.2011    source источник
comment
Привет, просто наблюдение, наличие второго потока, единственной целью которого в жизни является вызов селектора в основном потоке и ожидание, пока он не будет выполнен, как бы побеждает цель наличия второго потока.   -  person idz    schedule 07.05.2011
comment
Ты абсолютно прав. Вот почему я сейчас использую NSOperation. У меня только что возникла проблема с запуском асинхронного NSURLConnection не в основном потоке.   -  person Pierre    schedule 08.05.2011


Ответы (2)


Второй поток вызывает метод в основном потоке и ждет, пока не будет выполнен метод в блокировке условия. Это вызовет DEADLOCK. RequestLauncher не может быть запущен во втором потоке?

person Kazuki Sakamoto    schedule 07.05.2011
comment
Ну, я вызываю этот метод в основном потоке, потому что это асинхронный запрос, и ему нужен цикл выполнения, доступный только в основном потоке. Я жду, пока не закончу, чтобы одновременно было установлено только одно соединение. Код звучит хорошо для вас, кроме этого? Что я мог тогда сделать? - person Pierre; 07.05.2011

Наконец-то я получил ответ.
Я больше использую многозадачность C, объясняя путаницу здесь!

В принципе, код был почти хорош. Я думал, что сигнал делает то, что увеличивает значение «семафора», так что, если один поток сигнализирует 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  

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

person Pierre    schedule 07.05.2011