Multi-threaded safety is simply due to JIT controlling the visibility of the newly compiled code. First flush, then make it visible for execution, can't go wrong with that and scheduling won't matter.
Things get a lot more complicated when it comes to code patching, but the principle is similar.
I don't think that helps - the point is that the flush might not be effective if the flushing thread gets scheduled away from the core which has the stale I$ before it manages to fully issue the flush.
Or is the flush guaranteed to flush all cores caches? That would be a fairly unusual design.
IC IVAU instructions are broadcast to all cores in the same 'inner shareable domain' (all cores running the same OS instance are in the same inner shareable domain)
Things get a lot more complicated when it comes to code patching, but the principle is similar.