Я не уверен, насколько хорошо это поможет для конкретного приложения, с которым вы работаете, но вот два подхода, заимствованных из функционального программирования для написания многопоточного кода:
Неизменяемые объекты
Если вам нужно разделить состояние между потоками, состояние должно быть неизменным. Если одному потоку необходимо внести изменения в объект, он создает новую версию объекта с изменением, а не изменяет состояние объекта.
Неизменность не ограничивает тип кода, который вы можете написать, и не является неэффективным. Существует множество реализаций неизменяемых стеков, множество неизменяемых деревьев, которые составляют основу карт и наборов, и другие виды неизменяемых структур данных, и многие (если не все) неизменяемые структуры данных так же эффективны, как и их изменяемые аналоги.
Поскольку объекты неизменяемы, один поток не может изменить общее состояние под вашим носом. Это означает, что вам не нужно приобретать блокировки для написания многопоточного кода. Этот подход устраняет целый класс ошибок, связанных с взаимоблокировкой, блокировкой в реальном времени и условиями гонки.
Передача сообщений в стиле Erlang
Вам не нужно изучать язык, но взгляните на Эрланга, чтобы увидеть, как он приближается к параллелизму. Приложения Erlang могут масштабироваться практически до бесконечности, поскольку каждый процесс полностью отделен от всех остальных (обратите внимание: это не совсем процессы, но и не совсем потоки).
Процессы запускаются и просто запускают цикл ожидания сообщений: сообщения принимаются в виде кортежей, с которыми процесс может затем сопоставить шаблон, чтобы увидеть, является ли сообщение значимым. Процессы могут отправлять другие сообщения, но они равнодушны к тому, кто получает сообщение.
Преимущества этого стиля - устранение блокировок, когда один процесс завершается неудачей, он не разрушает все ваше приложение. Вот краткое изложение параллелизма в стиле Erlang: http://www.defmacro.org/ramblings/concurrency.html