It also would not be guaranteed safe in any program that installs a non-default interrupt handler. That is another class of program where reentrancy is important.
Multithreading is more common use case that gives problems in modern developments though. And since C11 has specifically included multithreading support, that is likely to be more important practically for C developers in the future. (Same for C++11).
That is the common way of creating DLLs, yes. It is not the only way. Shared memory (which is accessible across multiple address spaces) is fairly important in some applications, and is often supported using particular types of DLLs.
Threads in a program do share the process address space - in fact, that is often the point of using threads rather than concurrent processes - unless they are specifically designed to make use of thread local storage. Auto variables are usually thread-local (by default). Static variables are typically shared across threads.
The specifics are a little different than for windows DLLs, but the same possibilities exist.