Skip to main content

Why datatypes are marked as thread-safe instead of procedures? [Resolved]

In Rust, Send (or Sync) marker traits are used to indicate whether a value of a type (or a reference to that) can be worked on within threaded context.

However, it is an attribute of a function or a procedure that whether it is thread-safe, as frequently seen in C function man-pages (e.g. man 3 rand).

So, why rust is designed to apply such attributes to the datatypes instead of functions? like:

struct Foo { ... }

unsafe sync fn thread_safe_fn(foo: &Foo) { ... }

This way, any type can be used anywhere, but only sync functions can operate on shared data; which makes it possible to have for example a single Rc with defined operations of either atomic (sync) or non-atomic (!sync).

Question Credit: Mohammad Amin Sameti
Question Reference
Asked April 14, 2019
Posted Under: Programming
3 Answers

There is nothing intrinsic to a function that implies thread safety other than its awareness of what shared data may be modified, and how it protects that data. It is the data itself that exists in memory, and can be accessed from separate threads of execution, and not typically a function (unless you have a function whose code is modified after loading, but that's far more rare). In the case of C's rand() function, its implementation accesses shared data, and does not protect against concurrent access. From the man page you mention: "The function rand() is not reentrant, since it uses hidden state that is modified on each call."

If the language were written as you are describing, consider a situation where a utility function modifies Foo. If this utility function were marked as thread-safe, it would have to needlessly take locks and protect data that was not (necessarily) shared. Additionally, you want to only block threads from concurrent access of the same memory location, not block access to all entry points in a function, which would be a bit clumsier when the generic function has to serialize execution, instead of something protecting a specific piece of data.

credit: cyberbisson
Answered April 14, 2019

The question of "Thread Safety" essentially means "if I modify shared mutable data using multiple operations on multiple different threads, will I get the correct results or not?"

So, without even thinking about how thread safety works, let us just very stupidly analyze the above sentence in English. If we want a single place to put a property such as "thread safe", where can we put it? We cannot put it in the thread, since there is more than one thread. We cannot put it on the operation, since there is more than one operation. The only place to put it is on the data!

credit: Jörg W Mittag
Answered April 14, 2019
Your Answer