Multi-threading with Frameworks and Libraries

If you ever use a framework or library, the multi-threading model used in a dependency is one of the most important things to understand.

When I first heard this advice, I interpreted this to mean that I should be careful whether functions were thread safe. The question on my mind was: could I safely call methods of an instance on multiple threads concurrently? After all, when someone explains concurrency, they usually describe when two threads are trying to invoke the same method.

Later, I learned this is fundamentally the wrong question. It is rare that a framework or library has code that guards an individual method or an object instance. Most third party code either leaves all concurrency issues for you to solve or provides a way for you to call code on a designated thread.

If there are no concurrency guarantees, the library is easy to use in practice. You can assume that the third party code is like yours. Whether you guard individual methods, components, or entire systems, you can extend your concurrency patterns. In a way, having no concurrency guarantees is simpler to reason about and integrate.

When a framework or library requires you to use a designated thread, it often makes your calling code more complex. For instance, most GUI frameworks require you to call framework methods on the "main thread". Therefore, every time you are about to call a GUI framework method, you have to ask yourself: is the current code being called on the main thread? If work is being done on a background thread, you have to somehow dispatch the GUI framework method call back on the main thread. Usually, dispatching code on a designated thread is easy, but the difficulty is remembering that you need to make the switch.

When frameworks and libraries require callers to use a designated thread, it is serially queueing all the work so there are fewer possible concurrency issues. Instead of complexity in every method ensuring all the framework code is multi-thread safe, it can simplify the framework code.

Changing perspectives from worrying about concurrency in individual instances to entire components is one of the things I appreciated learning from experience rather than from school.