As far as I understand, dlls are actually by default executed in another thread too, but it won't give you any significant performance boost. (Someone please correct me if I am wrong on this bit.)
This may be different on some operating systems, but it was my impression that the DLL code was either copied into the process's address space or copied to a single location in memory, where the code would jump to it out of the original process when needed. It would jump back when done.
This is why there are issues with reentrancy and thread safety with DLLs: if the DLL code stores internal state and gets linked to two processes that do stuff, bad things can happen.
Of course, I could be completely off here since I've never even written a DLL. I just studied OS theory a bit without much practical application of it.
A .DLL gets
mapped into a processes address space, whereupon the functions defined in it become available.
Generally code does not modify itself so it
was considered safe for the OS to use 'copy on write' to use one real copy in RAM to serve multiple processes; however, nowdays with more RAM available, more address collisions, and 'ASLR' (see below) each process may have it's own unique copy.
In windows when a .DLL is loaded, if it can't have it's default address, Windows can quickly modify the tables at the beginning of the module to relocate it; that is, a .DLL may have been written to assume it's loaded at A0000000; but another .DLL was already loaded at A0000000, Windows puts the .DLL at B0000000 and goes through all the jumps to A0005678, A0008200, A000FF10 ... changing them to B0005678, B0008200, B000FF10 ... there usually isn't too many of them, since
most jumps are relative (like 20 instructions forward, or 17 back, etc)
ASLR is part of a security method where even if the default address is available, windows relocates the .DLL randomly anyway; that's because some exploits could force, for example, a jump to A0005678, and cause the code there to run, but if it's at AB005678, AF005678, 97005678... the exploit will fail; it'll still crash the process, but at least it won't format your boot drive. For anything possibly exposed to external data, it's worth the cost of shuffling things around.
When a .DLL is loaded and unloaded, specifically when a process or a thread starts or stops using it, predefined functions can be called
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583%28v=vs.85%29.aspxIt's really up to the .DLL if it was coded to support multithreading; if it only allocates a chunk of memory when the process attaches, it'll (probably) only support one thread, if it allocates memory as each thread spawns, it's probably designed to be multi-threaded. .DLL's are no more or less thread-safe than any other executable; however, you are generally only as safe as your weakest linked library.