how can I provide synchronization upon method parameter values?
All method calls using the 'same' parameter value A should be synchronized. A method call with a different parameter value e.g. B can access, even when calls with A are already waiting. The next concurrent call for B must wait also for the first B to be released.
My use case: I want to synchronize the access to JPA entities on ID level but want to avoid pessimistic locking because I need kind of a queue. The 'key' for locking is intended to be the entity ID - which is in fact of the type Java Long.
protected void entityLockedAccess(SomeEntity myEntity) {
//getId() returns different Long objects so the lock does not work
synchronized (myEntity.getId()) {
//the critical section ...
}
}
I read about lock objects but I am not sure how they would suit in my case. On the top level I want to manage a specific REST call to my application which executes critical code.
Thanks, Chris
Java Synchronized MethodSynchronized method is used to lock an object for any shared resource. When a thread invokes a synchronized method, it automatically acquires the lock for that object and releases it when the thread completes its task.
synchronized is not part of the method signature.
Yes, we can synchronize a run() method in Java, but it is not required because this method has been executed by a single thread only. Hence synchronization is not needed for the run() method.
As far as I understood you basically want a different, unique lock for each of your SomeEntity
IDs.
You could realize this with a Map<Integer, Object>
.
You simply map each ID to an object. Should there already be an object, you reuse it. This could look something like this:
static Map<Integer, Object> locks = new ConcurrentHashMap<>();
public static void main(String[] args)
{
int i1 = 1;
int i2 = 2;
foo(i1);
foo(i1);
foo(i2);
}
public static void foo(int o)
{
synchronized (locks.computeIfAbsent(o, k -> new Object()))
{
// computation
}
}
This will create 2 lock objects in the map as the object for i1
is reused in the second foo(i1)
call.
Objects which are pooled and potentially reused should not be used for synchronization. If they are, it can cause unrelated threads to deadlock with unhelpful stacktraces.
Specifically, String
literals, and boxed primitives such as Integers
should NOT be used as lock objects because they are pooled and reused.
The story is even worse for Boolean
objects because there are only two instances of Boolean
, Boolean.TRUE
and Boolean.FALSE
and every class that uses a Boolean will be referring to one of the two.
I read about lock objects but I am not sure how they would suit in my case. On the top level I want to manage a specific REST call to my application which executes critical code.
You DB will take care for concurrent writes and other transactional issues. All you need to do is use Transactions.
I would also recommend you to go through the classical problems (DIRTY READs NON Repeatable reads). You can also use Optimistic Locking for
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With