Thread worker simulator
1. Is the intent clear?

Not completely for me. As you're saying


  for the real thread code, leaving any other locks, mutexes, etc. in place, allows me to gain some insight as to how the various threads might run.


the closest intent I can grasp is, you want to eliminate certain threads by replacing them with worksim threads, to isolate other threads that might be the source of race conditions, dead locks or other multiple threading related problems in the to be tested code.

I'm not a 100% sure if these simplified threads may be really useful for diagnosis of the above mentioned problems. Especially as they won't affect other threads, other than with a random delay and don't touch those synchronization mechanisms left in place. To some degree may be.

2. Is the use of a static number generator OK here?

The instantiation of static local variables will be thread safe. Execution of operations like dist(gen)) will not guarantee thread safety.

The reference documentation about std::binomial_distribution::operator() doesn't tell anything about thread safety, and because gen is a shared resource between threads I would doubt about appropriate results.

3. is there a better way to handle the logging?

The standard I/O output can be fairly slow, and as I mentioned in my comment "The use of a shared logger with the mutex locking may severely influence your threads' runtime behavior".

A generally better approach might be to use the shortest possible lock to pass the log message to the logger (e.g. using a protected queue of std::unique_ptr's), and let the Logger class output these from another background thread (that's what we're using in our production systems).