Я мог бы предложить следующую схему. Как правило, можно использовать тот же метод, например, когда пребуферизует кадры в некоторых рендерерах в реальном времени или что-то в этом роде.
Во-первых, очевидно, что подход, который вы описываете в своем сообщении, будет эффективным , если оба ваших потока будут загружены одинаково (или почти одинаково) все время. Если нет, многопоточность действительно выиграет в вашей ситуации.
Теперь давайте подумаем о схеме потока, которая была бы оптимальной для вашей задачи. Предположим, у нас есть поток yielding
и processing
. Первый из них подготавливает куски данных к обработке, второй производит обработку и сохраняет результат обработки где-то (не очень важно).
Эффективный способ заставить эти нити работать вместе - это правильный механизм отдачи. Ваш поток yielding
должен просто добавлять данные в некоторый общий буфер и не должен заботиться о том, что произойдет с этими данными. И, ну, ваш буфер может быть реализован в виде простой очереди FIFO. Это означает, что ваш поток yielding
должен подготовить данные для обработки и сделать PUSH
вызов вашей очереди:
X = PREPARE_DATA()
BUFFER.LOCK()
BUFFER.PUSH(X)
BUFFER.UNLOCK()
Теперь поток processing
. Это поведение должно быть описано следующим образом (вам, вероятно, следует добавить некоторую искусственную задержку, например SLEEP(X)
между вызовами EMPTY
)
IF !EMPTY(BUFFER) PROCESS(BUFFER.TOP)
Важным моментом здесь является то, что ваш поток обработки должен делать с обработанными данными. Очевидный подход означает выполнение POP
вызова после обработки данных, но вы, вероятно, захотите придумать более удачную идею. Во всяком случае, в моем варианте это будет выглядеть как
// After data is processed
BUFFER.LOCK()
BUFFER.POP()
BUFFER.UNLOCK()
Обратите внимание, что операции блокировки в потоках yielding
и processing
на самом деле не должны влиять на вашу производительность, поскольку они вызываются только один раз для каждого фрагмента данных.
Теперь интересная часть. Как я писал в начале, этот подход будет эффективен только в том случае, если потоки будут работать примерно одинаково с точки зрения использования процессора / ресурсов. Существует способ сделать это решение для многопоточности эффективным, даже если это условие не всегда верно и имеет значение для некоторых других условий времени выполнения.
Этот способ означает создание другого потока, который называется controller
thread. Этот поток просто сравнил бы время, которое каждый поток использует для обработки одного куска данных, и соответствующим образом сбалансировал приоритеты потока. На самом деле нам не нужно «сравнивать время» , поток controller
может просто работать так:
IF BUFFER.SIZE() > T
DECREASE_PRIORITY(YIELDING_THREAD)
INCREASE_PRIORITY(PROCESSING_THREAD)
Конечно, вы могли бы реализовать некоторые лучшие эвристики здесь, но подход с потоком controller
должен быть ясным.