One example is if you use unsynchronized interior mutability. For example both Cell
and RefCell
implement Send
but not Sync
because it is fine to send one to another thread, because that thread now owns it and it no one else can access it. But it is not fine to share it because Cell
and RefCell
use interior mutability without synchronizing access. So if two different threads tried to access either of them there would be a data race.
Another case is if you are using trait objects.
Box<dyn Trait>: !Send + !Sync
Box<dyn Trait + Send>: Send + !Sync
Box<dyn Trait + Send + Sync>: Send + Sync
Box<dyn Trait + Sync>: !Send + Sync
The reason for this is because if you don't mark the trait object Send
or Sync
you can put types inside that are not Send
or Sync
.
It looks like DirectoryLock
is only Send
because of the Box<Drop + Send + 'static>
inside of it (from looking at the source code).