Some background: I created a contrived example to demonstrate use of VisualVM to my team. In particular, one method had an unnecessary synchronized
The same problem as here.
You're actually measuring the contention inside a PRNG with a shared state.
JDKRandomGenerator is based on java.util.Random which has seed shared among all your worker threads. The threads compete to update seed in the compare-and-set loop.
Why lock improves performance then? In fact, it helps to reduce contention inside java.util.Random by serializing the work: while one thread performs matrix multiplication, the other is filling the matrix with random numbers. Without lock threads do the same work concurrently.