It is not as straightforward as in stop-the-world-gc languages or manual-memory-management languages and requires some mental exercises. Here are some tips that combined could help with that.
1. Non-gc allocated data (allocShared and friends) can be shared freely across the threads. Provided you do proper syncing of course. 2. Non-gc backed fields of a ref object can be modified in "foreign" thread. Just make sure to guarantee sufficient lifetimes. 3. There are a couple of "shared" containers in nim std lib, like SharedArray, SharedTable, iirc. But you can't populate those with gc-backed data. 4. There's message passing as a different idiom. It will work with refs but will do deep copies under the hood. That's not what you are asking about, but an option to rethink your design. 5. Maybe @Araq can suggest some regions or RAII approach, but that's something I don't know about.
