I made good experiences with an intermediate helper object, holding only data to be shared like status info, abort flags etc shared between threads. That will not fit all cases, but it does quite often for me.
The helper instance should implement (and encapsulate) locking in its methods, getters and setters as required, so you don't have to deal with it on the outside.
Consistent, thread safe, easy to use.