tezvyn:

How do Send and Sync prevent data races? Give a Send-but-not-Sync example.

AI-drafted, machine-checkedSource: doc.rust-lang.orgbeginner
WHAT IT TESTS

Rust's thread-safety model.

ANSWER OUTLINE

explain Send moves values and Sync allows shared references across threads; give Cell as Send but not Sync because it has interior mutability.

RED FLAG

conflating them or naming Rc, which lacks both.

WHAT THIS TESTS: This question probes whether you understand how Rust encodes thread safety directly into the type system. The interviewer wants to see that you know Send and Sync are unsafe marker traits automatically derived by the compiler, and that you can explain the difference between transferring ownership to another thread versus sharing references across threads. They also want a concrete type that breaks symmetry: something you can move to another thread but cannot safely share between threads.

A GOOD ANSWER COVERS: First, define Send as the guarantee that a value can be moved into another thread without data races. Second, define Sync as the guarantee that a type can be shared via immutable references across threads, which is equivalent to saying that a shared reference to T is itself Send. Third, note that both traits are automatically derived for composite types when all their fields implement them, which is why most Rust code is thread-safe by default. Fourth, provide a simple example of a type that is Send but not Sync, such as Cell or RefCell, and explain that this is because they allow interior mutability without synchronization primitives.

COMMON WRONG ANSWERS: A major red flag is offering Rc as Send but not Sync. Rc is actually neither Send nor Sync because its reference count is unsynchronized shared mutable state. Another red flag is describing Send and Sync as runtime checks or garbage-collection mechanisms; they are compile-time marker traits with no methods. Confusing the two definitions, such as saying Sync lets you move values, also signals a shallow understanding. Finally, claiming that raw pointers are Send or Sync is incorrect; they are explicitly neither to prevent automatic derivation for types that contain them.

LIKELY FOLLOW-UPS: The interviewer may ask why raw pointers are neither Send nor Sync even though dereferencing them is already unsafe. They might also ask you to implement a custom wrapper around a raw pointer and justify when it would be sound to manually implement Send or Sync. Another follow-up is asking how Mutex or atomic types restore Sync semantics for interior mutability. You might also be asked to explain negative impls or why the standard collections are Send and Sync despite using raw pointers internally.

ONE CONCRETE EXAMPLE: A clear example is Cell. You can create a Cell on one thread and move it to another, so it is Send. However, if two threads held shared references to the same Cell, they could both call get or set on it simultaneously, causing a data race because Cell uses unsynchronized interior mutability. Therefore Cell is not Sync. In contrast, an atomic integer is both Send and Sync because its operations are hardware-synchronized, and a vector of integers is both because it owns its data and exposes no unsynchronized shared mutation.

Read the original → doc.rust-lang.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.