Синхронизация 3 потоков, разделяющих буферы, используя NSConditionLock.Это тяжело - PullRequest
0 голосов
/ 16 февраля 2011

У меня 3 темы (в дополнение к основной теме).Потоки читают, обрабатывают и пишут.Каждый из них делает это с несколькими буферами, которые циклически повторяются и используются повторно.Причина, по которой он настроен таким образом, заключается в том, что программа может продолжать выполнять другие задачи, пока одна из них работает.Так, например, когда программа пишет на диск, она может одновременно читать больше данных.

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

Поток чтения считывает данные в буфер, а затем отмечает буфер как «новые данные» в массиве.Итак, это работает так:

//set up in main thread
NSConditionLock *readlock = [[NSConditionLock alloc] initWithCondition:0];

//set up lock in thread
[readlock lockWhenCondition:buffer_new[current_buf]];

//copy data to buffer
memcpy(buffer[current_buf],source_data,data_length);

//mark buffer as new (this is reset to 0 once the data is processed)
buffer_new[current_buf] = 1;

//unlock
[readlock unlockWithCondition:0];

Я использую buffer_new [current_buf] как переменную условия для NSConditionLock.Если буфер не помечен как новый, то рассматриваемый поток заблокируется, ожидая, пока предыдущий поток запишет новые данные.Эта часть работает нормально.

Основная проблема в том, что мне нужно синхронизировать это в в обоих направлениях .Если поток чтения по какой-то причине занимает слишком много времени, и поток обработки уже завершил обработку всех буферов, поток обработки должен ждать и наоборот.

Я не уверен, что NSConditionLock являетсяподходящий способ сделать это.

Ответы [ 2 ]

2 голосов
/ 16 февраля 2011

Я бы перевернул это с ног на голову.Как вы говорите, многопоточность сложна, а многопоточная синхронизация потоков еще сложнее.Параллелизм на основе очередей часто намного более естественен.

Определите три очереди;очередь чтения, очередь записи и очередь обработки.Затем используйте правило, гласящее, что ни один буфер не должен ставиться в очередь более чем в одну очередь за раз .

То есть буфер может быть поставлен в очередь на очередь чтения и, после завершения чтения, поставлен в очередь на очередь обработки, а после завершения обработки помещен в очередь на запись.

Вы можете использоватьесли хотите, стек буферов, но, как правило, стоимость размещения довольно низкая по сравнению со стоимостью обработки, и, таким образом, enqueue-for-read может также выполнить выделение, тогда как dequeue-Once-Writed может сделать бесплатное.

Это было бы довольно просто для кода с GCD.Обратите внимание, что если вы действительно хотите параллелизма, ваши различные очереди будут на самом деле просто дросселями, используя семафоры - потенциально совместно используемые - для постановки работы в глобальные параллельные очереди.

Обратите также внимание на то, что этот дизайн имеет явное преимуществосверх того, что вы используете в данный момент: не использует блокировок .Единственные блокировки скрыты под API GCD как часть управления очередью, но это фактически невидимо для вашего кода.

1 голос
/ 16 февраля 2011

Видели ли вы тогда Руководство по программированию параллелизма Apple?

В нем рекомендуется несколько предпочтительных методов отказа от модели параллелизма Threads and Locks.Например, использование очередей операций может не только уменьшить и упростить ваш код, ускорить разработку и повысить производительность.

Иногда вам нужно использовать потоки, и у вас уже есть правильная идея.Вам нужно будет продолжать добавлять блокировки, и с каждым это будет экспоненциально усложняться, пока вы не сможете понять свой собственный код.Затем вы можете начать добавлять блокировки в случайных местах.Тогда вы облажались.

Прочтите руководство по параллелизму и следуйте советам bbum.

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