Why does reentrantlock exist? Well, one reason is that it supports APIs like tryLock and multiple condition variables.
Why is it faster than synchronized? This is probably because (depending on your jvm) ReentrantLock is built on LockSupport.park, which is virtual thread aware, and synchronized is operating directly on the platform threads.
Did you use fair scheduling with ReentrantLock? That could account for a difference of intrinsic locks (synchronized) was a fair lock.
This type of benchmark is a pathological because the optimal scheduling policy is for one thread to starve all the others until it finishes, which is basically never what you'd want in a real project.
AFAIK synchronized isn't a fair lock but according to the spec it's implementation dependent.
The numbers are bad because OP is using manual benchmarking and falling for the microbenchmarking traps with JIT optimizations. There's no warmup or anything...
I tried both fair and the default, it didn’t make a significant difference.
People have pointed out that I should probably be using something like JMH instead of basic timers. I plan on writing an update to this with those numbers.
Why is it faster than synchronized? This is probably because (depending on your jvm) ReentrantLock is built on LockSupport.park, which is virtual thread aware, and synchronized is operating directly on the platform threads.