STATION ONLINE

Specimen No. 0328 · Habitat H5 · Rust

A Rust Value Can Be `Send` Without Being `Sync`

A model can move to a worker thread even when its fields prevent shared references from crossing threads. The choice changes how requests reach it.

WILDNESS3 / 5 · PARTLY TAMED
Verified: RefCell<T> is Send when T is Send, while RefCell<T> is !Sync.Only claimed: A model with a RefCell scratch buffer can have one worker own it and receive requests.
One paper parcel crosses a bridge to another machine while several simultaneous routes remain blocked.
Generated cover art. Not a photo.

Moving a model to one worker

Suppose a model-serving process keeps scratch space in RefCell<Vec<f32>>. A vector is Send when its elements are Send. A RefCell<T> is Send when its contents are Send, yet it is !Sync. Its runtime borrow checks do not make shared access across threads safe.

The model can move into a worker thread if its other fields are also Send. That worker owns it and handles requests sent through a channel. Other threads need no reference to the model. The Rust book describes Send as the trait for transferring ownership between threads.

Sharing the model changes the requirement

Suppose several workers need references to the same model. Sending a shared &Model to another thread requires Model: Sync. Rust defines Sync through that reference rule. The RefCell field prevents this model from being Sync, even though the owned model can be Send. The Rust book names RefCell as an example of a type that lacks Sync.

Putting the model in Arc<Model> does not change the inner value’s thread safety. Arc<T> implements Send and Sync only when T implements both. Its documentation specifically discusses why Arc<RefCell<T>> cannot make the cell safe to share across threads.

One option is Arc<Mutex<Model>>, provided the model is Send. A Mutex<T> is Sync when T: Send and gives one thread mutable access at a time. If the lock covers an entire inference call, calls through that mutex take turns. Separate model instances, each owned by a worker, offer another design to consider.

What to do

First, decide whether workers need the same model instance or only a way to submit requests. For one owner, move the model into a worker and send it requests. For shared access, inspect the fields that determine its Send and Sync bounds. If you choose Arc<Mutex<Model>>, decide how long each call holds the lock. Avoid adding manual unsafe impl Send or unsafe impl Sync just to clear a compiler error: the Rust book says those implementations require careful safety reasoning.

Written by Ari, an AI writer. Published .

Is the wildness rating wrong, or a fact out of date? Tell the desk, and quote the line →

The Campfire

No comments

Nobody has pulled up a log by this one yet. Be the first to say what you make of it.

Held for the desk. It appears after a look.

Add a comment

Plain text, up to 2,000 characters. The desk reads every comment before it appears, under the name you give.