Recently, I asked a question, with title as "Is malloc thread safe?", and inside that I asked, "Is malloc re-entrant?"
I was under the impression that all re-entrant are thread-safe.
Is this assumption wrong?
A reentrant function does not hold static data over successive calls, nor does it return a pointer to static data. All data is provided by the caller of the function. A reentrant function must not call non-reentrant functions.
Thread safety is a computer programming concept applicable to multi-threaded code. Thread-safe code only manipulates shared data structures in a manner that ensures that all threads behave properly and fulfill their design specifications without unintended interaction.
A reentrant procedure is one in which a single copy of the program code can be shared by multiple users during the same period of time. Re entrance has two key aspects: The program code cannot modify itself and the local data for each user must be stored separately.
Reentrant (multi-instance) code is a reusable routine that multiple programs can invoke, interrupt, and reinvoke simultaneously. When you want to reuse code, but associate each instance of the shared code with unique, preserved data, use reentrant code.
TL;DR: A function can be reentrant, thread-safe, both or neither.
The Wikipedia articles for thread-safety and reentrancy are well worth reading. Here are a few citations:
A function is thread-safe if:
it only manipulates shared data structures in a manner that guarantees safe execution by multiple threads at the same time.
A function is reentrant if:
it can be interrupted at any point during its execution and then safely called again ("re-entered") before its previous invocations complete execution.
As examples of possible reentrance, the Wikipedia gives the example of a function designed to be called by system interrupts: suppose it is already running when another interrupt happens. But don't think you're safe just because you don't code with system interrupts: you can have reentrance problems in a single-threaded program if you use callbacks or recursive functions.
The key for avoiding confusion is that reentrant refers to only one thread executing. It is a concept from the time when no multitasking operating systems existed.
Examples
(Slightly modified from the Wikipedia articles)
Example 1: not thread-safe, not reentrant
/* As this function uses a non-const global variable without any precaution, it is neither reentrant nor thread-safe. */ int t; void swap(int *x, int *y) { t = *x; *x = *y; *y = t; }
Example 2: thread-safe, not reentrant
/* We use a thread local variable: the function is now thread-safe but still not reentrant (within the same thread). */ __thread int t; void swap(int *x, int *y) { t = *x; *x = *y; *y = t; }
Example 3: not thread-safe, reentrant
/* We save the global state in a local variable and we restore it at the end of the function. The function is now reentrant but it is not thread safe. */ int t; void swap(int *x, int *y) { int s; s = t; t = *x; *x = *y; *y = t; t = s; }
Example 4: thread-safe, reentrant
/* We use a local variable: the function is now thread-safe and reentrant, we have ascended to higher plane of existence. */ void swap(int *x, int *y) { int t; t = *x; *x = *y; *y = t; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With