Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java synchronized method around parameter value

Consider the following method:

public void upsert(int customerId, int somethingElse) {
  // some code which is prone to race conditions    
}

I want to protect this method from race conditions, but this can only occur if two threads with the same customerId are calling it at the same time. If I make the whole method synchronized it will reduce the efficiency and it's not really needed. What I really want is to synchronize it around the customerId. Is this possible somehow with Java? Are there any built-in tools for that or I'd need a Map of Integers to use as locks?

Also feel free to advice if you think I'm doing something wrong here :)

Thanks!

like image 914
Anton Belev Avatar asked Sep 14 '16 12:09

Anton Belev


1 Answers

The concept you're looking for is called segmented locking or striped locking. It is too wasteful to have a separate lock for each customer (locks are quite heavyweight). Instead you want to partition your customer ID space into a reasonable number of partitions, matching the desired degree of parallelism. Typically 8-16 would be enough, but this depends on the amount of work the method does.

This outlines a simple approach:

private final Object[] locks = new Object[8];

synchronized (locks[customerId % locks.length]) {
    ...implementation...
}
like image 50
Marko Topolnik Avatar answered Oct 18 '22 19:10

Marko Topolnik