There is a HashMap , which contains a list of orders. It may happen that several threads simultaneously try to accept an order.

In order to avoid such a situation, I try to put a lock on a list item (but not on the entire list, so as not to interfere with reading and similar processing of other elements):

 Order order = map.get(id); if (order != null && !order.isAccepted()) { synchronized (map.get(id)) { if (map.get(id) != null && !map.get(id).isAccepted()) { map.get(id).accept(); } } } 

First, I pull out the object and check the required condition on it so that it does not become null during the condition check. Then I block this item in the list and re-check the condition (it could have changed during the test of the first condition), after which the action is taken.


Is it worth using the blocking of one element, does it really allow working with other elements without blocking the list and does this blocking cause problems (for example, during deletion)?

  • 2
    If map.get(index) inside the synchronized block returns null , then the NullPointerException will end. If another object is written between synchronized and the internal if in map using the index key (strangely, the key is called the index), then accept will be called for an object that is not associated with the synchronized object. - Regent
  • Does the list of orders change in parallel? Are orders added / deleted? - default locale
  • You need banal striped locks - etki
  • @Regent, is it possible to somehow improve my mechanism or should I simply switch to the synchronized implementation? - Rostislav Dugin
  • @defaultlocale, yes. - Rostislav Dugin

1 answer 1

In the documentation for the class ConcurrentHashMap , it turns out (surprisingly, for such a frequent problem, a solution has already been invented :)), there is a ready-made solution in the form of the compute method, which accepts the function and performs it atomically with blocking!