I don't really see how threading has anything to do with it.
What OOP allows you to do is choose what terms you want to express your solution in. You can choose language that exposes thread-safe aspects of your problem domain without requiring the user to be aware that they are expressing things in thread-safe terms. In my last project one of the early elements of our architecture was a thread-safe message queue for each thread to receive messages from across the thread boundary. Discussions on our team involved talk of messaging and threading because those were the abstractions we chose to use to express our solution.
We knew that order of access was important and so we chose to make it explicit in the language we used to express the problem. And the abstraction we chose allowed us to hide the details of the problem in such a way that we did not have to worry about memory protection as long as we were consistently using the architecture we built. That was a concern of the messaging system's maintainer. We could just as easily have chosen rows and columns and operators on such and expressed the same solution in those terms. What mattered to us was making sense of the problem, domain and solution.
It really doesn't matter which paradigm you use. What matters more is that you express your solution in terms that are consistent with the problem domain, and that you actually make an effort to understand the problem you're trying to solve well enough to express the solution. Anything beyond that is just sugar.
Mutability is rarely needed and often makes things more complicated than needed.
Now if you want to talk about specific languages, then I would generally agree with you about C++ and C, but then there are ways you can design a program in those languages to be thread-safe. With FP you're just choosing a different solution to the problem which comes with its own drawbacks in some cases.
I agree if you stay in purely functional programming languages you run into points that are solved better with mutability. However those parts of a program are small and most parts are expressed better by pure functions.
Thread safety can't be expressed or enforced and you can't grab a bunch of classes from somewhere and assume anything about their fitness for multi-threaded code.
Typically one has to carefully design a class for multi-threaded use. Reasoning about state inside objects then quickly becomes infeasible.
What's a couple orders of magnitude of performance and some heavyweight link time dependencies between objects?
I'd go as far to say that even if you're not targeting multiple threads, accounting for them in this way (NOT the stupid "just put a lock on each object" way) results in much better/simpler code.
What if this exposure occurs at the boundaries of your system, or when interacting with certain libraries? Surely there's value as "mostly" handling some things as objects within your system, even if you expose their innards and maybe break their invariants at the boundaries.
Yet, there is a well-known pattern, which is to have objects each running on its own thread. (Incidentally, this gives a new - I'd say, true - meaning to the notion of 'message passing' as the idea of how objects are to communicate.)
And how many objects do you want to run in its own thread? 10k? 100k?
Now, you'd need something lighterweight than many threading libraries (such as C++ and Java programmers usually use), you'd want something closer to Erlang's process model.
Problems will occur if you need to convert the innards of your objects to data (i.e. JSON etc.), if you need to materialize objects from data (i.e. ORM) or if you need to write multi-threading safe code.
If you expose things as data, just be honest about it and treat it as such. It's already out in the open, why hide it in objects again?