There is no trick to it, the ShadingSystem is thread-safe for shader execution.
If you are buliding from master, then for declarations of shaders (i.e., ShadingGroupBegin, Shader, ConnectShaders, Parameter, ShaderGroupEnd), just be careful to use the new, thread-safe versions, not the old ones that are not thread safe. Read the oslexec.h header, it's pretty clear about which are which.
If you are using 1.10 or older, then the declaring of shaders is not thread-safe, it only has the old versions. So you want to declare your shader groups from one thread (or at least have a mutex to make sure two threads aren't declaring different shaders at the same time).
In both master and release branches, though, the execution of shaders is already totally thread-safe.
Basically, you just call shadingsys->execute(ctx, group, globals). The ctx is a pointer to a ShadingContext (which you acquire via get_context(), and is thread-specific). Don't share a context between different threads -- have each thread get its own context and then keep using it.
That's all there is to it.
Both the testshade and testrender programs that we use extensively in the unit tests are multithreaded, so you can also look at those for examples.