Блокировки бывают разные и стоимость их тоже разная, но в любом случае принимая данные из внешнего источника в темпе реального времени всегда нужно думать о временных диаграммах и о том, что иногда они нарушаются.
И вот тогда надо чем-то жертвовать: либо вы пропускаете какой-то блок данных, но гарантируете корректность обработки, либо гарантируете прием данных, но не гарантируете корректность его обработки.
Я так понимаю у вас математика отработает быстрее, чем вы примите новую порцию данных, это значит что выпадение из диаграммы по отставанию обработки мало вероятен. Поэтому поток принимающий данные высвобождает condition, а это операция практически ничего не стоит.
По сравнению с этим доставка сигнала в очередь на обработку в другой поток на порядок более дорогая операция.
Тогда вам действительно нужен третий поток и кольцевой буфер. Синхронизацию между потоком данных и математикой лучше делать через QWaitCondition,он быстрее STL-вского (личный опыт). Либо брать из boost он еще быстрее.
В нем же можно найти кольцевой буфер.
А вот до Гуи я всеравно предлагаю доставлять данные через сигналы.