Also, multithreading code isn’t that simple or easy. We tend to look at that as an easy solution that fits all purposes and fixes everything. I know I used to.
Thing is that multithreading adds overhead, splitting tasks into threads and then sending those to the cores has a lot of overhead, there isn’t an automatic way to do it, the coder must deal with that. When tasks are very easy to parallelize and take a lot of time (example, rendering tiles) then the overhead is negligible and the benefits of multithreading are very obvious.
But when tasks are smaller, faster and you must work around them to parallelize… the overhead eats up any benefits and multithreading becomes a burden.
If it was that easy, everybody would do it everywhere, and truth is it doesn’t happen that much. Games have just started parallelizing stuff since those now use multiple passes for rendering frames after geometry is processed, and you can parallelize those passes, but without those… you’d be stuck on single threads as it’s always been the case.