I am reading through Mara's book on atomics and locks, and in the chapter 4 they are building a primitive SpinLock
(implementation is listed below).
And while implementing Sync
trait, the following is emphasized:
However, since the lock can be used to send values to type
T
from one thread to another, we must limit this promise to types that are safe to send between threads. So, we (unsafely) implementSync
forSpinLock<T>
for allT
that implementSend
, like this:
unsafe impl<T> Sync for SpinLock<T> where: T Send {}
So the question is, why do we need T: Send
bound? What does it mean that "the lock could be used to send values from one thread to another"? I mean, only one thread owns the lock, and the only thing that shared is the mutable reference to the value (so should we require only Sync
instead?). Or, otherwise, what could go wrong if this bound isn't present?
Here is implementation of the spin lock for more details:
struct SpinLock<T> {
locked: AtomicBool,
storage: UnsafeCell<T>,
}
unsafe impl<T> Sync for SpinLock<T> where T: Send {}
impl<T> SpinLock<T> {
pub fn lock(&self) -> &mut T {
while self
.locked
.compare_exchange_weak(false, true, Acquire, Relaxed)
.is_err()
{
std::hint::spin_loop();
}
unsafe { &mut *self.storage.get() }
}
pub unsafe fn unlock(&self) {
self.locked.store(false, Release);
}
}
Thanks in advance!