Isolates are like synchronous state machines. During each handler invocation, an isolate processes one message, mutates its private state, and chooses its next scheduler action. If IO is needed, it returns an IO Effect describing the IO, the isolate is parked, and the eventual IO result is delivered through a later completion message. In the meantime it continues to handle messages of other isolates.
Edit: And I realized you asked about compute-heavy tasks, nevermind, it does not seem to solve that.