Я думаю, что правильный подход - это не один файл на поток, а один поток на файл. Если какой-либо один файл (или ресурс в целом) в вашей системе когда-либо доступен только одному потоку, поточно-ориентированное программирование становится намного проще.
Так почему бы не сделать Logger выделенным потоком (или несколькими потоками, по одному на файл, если вы регистрируете разные вещи в разных файлах), а во всех других потоках запись в журнал поместит сообщение в очередь ввода в соответствующий поток Logger, который получит к нему после завершения написания предыдущего сообщения. Все, что требуется, - это мьютекс, чтобы защитить очередь от добавления события, пока Logger читает событие, и condvar для Logger, чтобы ждать, когда его очередь пуста.