Hi Chaoyu this is a great idea.
Thought I'm a little concerned that 'conflictingLocks' is a member variable of the shared ZKLockManager instance. Would that be an issue with different threads calling lock() at same time, as they are sharing access on the variable? Can it be done differently, for example if lock() method passed in a flag to lockPrimitive() telling it whether to print the log? Then it can just make the 'conflictingLock' list locally in the method and print it. Also appreciate a RB for easier viewing