methods: add a lock around method table changes (#52997)
Ensures that only one update can occur simultaneously by adding a lock
around it, and that the acquire-release on the world-age will be
sequenced after all of the invalidations to the caches, by updating it
last.
It should now be safe to add methods in parallel, concurrently with
running code. However, there are still no locks here to ensure that only
one module is deserialized at a time, which means that parallel require
calls are still unsafe. (and also because the loading.jl code is
currently a thread-safety disaster zone)
As future work, all of the method inserting and (separately) the
validation/insertion work could run in parallel after loading an image,
since there is a fine-grained lock on each individual part of that, as
well as the big lock so that only one module at a time can load methods.
The min/max fields are always written behind a lock, but they are not
usually read from behind a lock, so add relaxed atomic markers to all
uses of that field to make any data-race analysis tools happy. These are
never used in a comparison with a value greater than
`jl_atomic_load_acquire(&jl_world_counter)`, and therefore the results
achieved are consistent.