This is what happens during C++ DLL startup:
- System calls DLL's entry point, generated by you compiler
- Entry point calls DllMainCRTStartup (name may differ), which initializes C/C++ runtimes and instantiates all global objects.
- DllMainCRTStartup then calls user-defined DllMain.
I personally prefer DllMain, because this way I can explicitly control order of initialization. When you use global objects in different compilation units, they will be initialized in random order which may bring some unexpected surprises 10 minutes before the deadline.
DllMain also let's you do per-thread initialization, which you can not achieve with global objects. However, it is not portable to other platforms.
P.S. You do NOT need mutex in DllMain, as all calls to it are already serialized under process-global critical section. I.e. it is guaranteed two threads will not enter it at the same time for any purpose. This is also the reason why you should not communicate with other threads, load other libraries etc. from this function; see MSDN article for explanation.