This is mostly a problem with citra-qt, since that frontend uses a separate thread for emulation code and frontend code.
For example, renderer_opengl.cpp L388 and emu_window.h L229 operate on different threads with no synchronization, and both access the emu_window class's framebuffer_layout variable.
This particular race condition actually causes a bug on OS X (release, not debug), where resizing the window does not correctly reposition the emulated screens.
Other race conditions involve configuration, where different threads might access the config singleton, and input, where one thread might trigger a keypress and another read it with no synchronization.
I strongly believe that to solution to this is _not_ to simply do the minimum amount of work required to synchronize accesses using mutexes or atomics and calling it a day. (Though such an incremental improvement would probably be welcome anyway.) Rather, I think the communication between the frontend(s) and the emulation core should be re-structured around a message queue that centralizes passing of information (such as input state, configuration changes, emulation state changes (such as pausing/stopping), requests for HLE UIs in the future, etc.) between the core and the frontend.
Most helpful comment
I strongly believe that to solution to this is _not_ to simply do the minimum amount of work required to synchronize accesses using mutexes or atomics and calling it a day. (Though such an incremental improvement would probably be welcome anyway.) Rather, I think the communication between the frontend(s) and the emulation core should be re-structured around a message queue that centralizes passing of information (such as input state, configuration changes, emulation state changes (such as pausing/stopping), requests for HLE UIs in the future, etc.) between the core and the frontend.