Welcome, concurrency is hard! Have you tested this code? Do you have unit tests? I suspect the code isn't correct and codereview is primarily for working code.
In your
releasemethod, you are callinglock.lock(), which is locking access tocombinationand right after you are callingisLocked()method, which wants to use the same lock. That doesn't seem correct and probably causes deadlock. Instead just directly checkcombinationfor null right there.Also public
isLockedmethod seems useless. What is the point of it and it's lock? If you acquire lock for such a short time (just to get theboolean, the information from the method is useless, because it may be outdated very fast. And if you want to react to it, you want to do it in atomic way. The alternative is to remove the lock from it, because it doesn't really do anything useful for you in this case.I would be careful with returning
nulls (even your sample usage can throwNullPointerExceptionwhenacquirefails!). In youracquiremethods, consider usingOptionalor throwing exception instead.To ensure the
lockis always locked or unlocked, less error-prone is to have some basic skeleton of a method, that does this for you and then in the "middle" executes your functional block. Then your atomic critical section are those lambdas and they are separated from synchronization code, which is in one place. The code is cleaner and less error-prone.I see no point of
Combinationclass existence. Is it to make sure that you don't release incorrectCombinationLockinstance?