The image below shows the setup. Both threads (update and render) run concurrently in an interactive loop, each having its own copy of the command queue. Our aim is to synchronize the threads, so that at the end of each frame (loop), there's a short window (during which the render thread is paused), which then allows to swap the unprotected command queues without any harm (the swap is invoked from the update thread). So in this case, we protect shared resources by thread cooperation rather than by explicit locking.

In the code below, I make use of a simple auto-reset event, which combines std::mutex and std::condition_variable into a single synchronization primitive. This proves to be quite convenient in this particular scenario.