Search code examples
multithreadingrustsynchronizationthread-safety

Why is !Send trait implemented for a RwLockReadGuard and RwLockWriteGuard in Rust?


I recently bumped across issues while trying to make a parallel system using the "Lock Guards" returned by RwLock. I needed to store these locks due to architectural design of my system. To my surprise, the types which stored these Lock Guards in failed to implement the Send trait, which lead me to explore the source code implementation of these guards, and sure enough, I found !Send trait implemented for these types.

I couldn't find any viable explanation for why is the !Send trait implemented for these types. So why is this the defined behaviour in the Rust standard library?

(My guess is that the RwLock uses a sys::RwLock in its structure, which stores an AtomicU32, which must be a thread local state, because in general we cannot transfer anything across thread boundary which is dependent on the thread local state of the thread it was generated lock, but again I'm not really sure)


Solution

  • This is because on some platforms a lock must be released on the same thread it was acquired. Since Rust is using the platform's synchronization primitives, it must adhere to this.

    For example, ReleaseSRWLockExclusive(), that is used on Windows <=7.

    If you need sendable guards, you can use parking_lot with the send_guard feature.