Java synchronized method around parameter value

前端 未结 2 1581
梦毁少年i
梦毁少年i 2021-01-06 01:57

Consider the following method:

public void upsert(int customerId, int somethingElse) {
  // some code which is prone to race conditions    
}
相关标签:
2条回答
  • 2021-01-06 02:07
        private static final Set<Integer> lockedIds = new HashSet<>();
    
        private void lock(Integer id) throws InterruptedException {
            synchronized (lockedIds) {
                while (!lockedIds.add(id)) {
                    lockedIds.wait();
                }
            }
        }
    
        private void unlock(Integer id) {
            synchronized (lockedIds) {
                lockedIds.remove(id);
                lockedIds.notifyAll();
            }
        }
    
        public void upsert(int customerId) throws InterruptedException {
            try {
                lock(customerId);
    
                //Put your code here.
                //For different ids it is executed in parallel.
                //For equal ids it is executed synchronously.
    
            } finally {
                unlock(customerId);
            }
        }
    
    • id can be not only an 'Integer' but any class with correctly overridden 'equals' and 'hashCode' methods.
    • try-finally - is very important - you must guarantee to unlock waiting threads after your operation even if your operation threw exception.
    • It will not work if your back-end is distributed across multiple servers/JVMs.
    0 讨论(0)
  • 2021-01-06 02:16

    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...
    }
    
    0 讨论(0)
提交回复
热议问题