Solving producer-consumer issues with multi-threaded synchronization