-2

I understand that Concurrent HashMap allows only a single thread at a time to update/write operation for "each segment". However multiple threads are allowed to read values from the map at the same time.
For my project, I want to extend this functionality such that while getting a value from a particular segment, no update/write operations should take place in that segment until read is completed.

Any ideas to achieve this?

  • Implement [ConcurrentMap](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentMap.html) with your desired functionality. – Mena Aug 16 '16 at 14:49

3 Answers3

1

Just to elaborate on the problem I'm facing right now. After reading a value from the map I perform certain update operations which are strongly dependent on that read value. Thus if a separate thread updates a key value and another threads get() fails to get the most recently updated values, this will lead to a big mess. So in this case extending would be a good idea?

My gut says no. Extending ConcurrentHashMap does not sound like a good idea.

One of the most valuable design principles to which you can adhere is called "Separation of Concerns." The main "concern" of a HashMap is to store key/value pairs. Sounds like maintaining consistent relationships between certain data in your program is another concern.

Don't try to address both concerns with a single class. I would create a higher-level class to take care of maintaining the consistent relationships (maybe by using Lock objects), and I would use a plain HashMap or ConcurrentHashMap to store the key/value pairs.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
0

Extend the ConcurrentHashMap class, and implement the getValue() method by including a synchronized block, so that no access is allowed to other threads until the read operation is completed.

Vicente Freire
  • 258
  • 1
  • 6
  • Thanks for the advice. Just to elaborate on the problem I'm facing right now. After reading a value from the map I perform certain update operations which are strongly dependent on that read value. Thus if a separate thread updates a key value and another threads get() fails to get the most recently updated values, this will lead to a big mess. So in this case extending would be a good idea? – Chelseafc26 Aug 16 '16 at 15:09
0

Informally, you can think of a Map as an set of "variables", each "variable" is addressed by a key (instead of a static name of an ordinary variable).

(An array is formally a list of variables, each addressed by an integer index.)

In HashMap, these "variables" are like "plain" variables; if you access a "variable" concurrently, things may go wrong (just like ordinary non-volatile variables)

In ConcurrentHashMap, these "variables" have volatile semantics. Therefore it is "more" safe to use concurrently. For example, a write will be visible to the "subsequent" read.

Of course, volatile is not enough sometimes; for example, we know we cannot use a volatile int for atomic increments (without locking). We need new devices, like AtomicInteger, for atomic operations.

Fortunately, in Java 8, new atomic methods are added to ConcurrentHashMap, so that now we can operate on these "variables" atomically. See if the compute() method may fit your use case.

ZhongYu
  • 19,446
  • 5
  • 33
  • 61
  • Thanks! Computer seems to be a great option. According to the documentation - "Some attempted update operations on this map by other threads may be blocked while computation is in progress, so the computation should be short and simple, and must not attempt to update any other mappings of this Map." The only concern is the "may be blocked" part – Chelseafc26 Aug 16 '16 at 15:44
  • For non-blocking concurrency, we often can use CAS - "compare and swap". We read the current value (v0), do some (lengthy) computation to get v1, we then attempt to set the value to v1 **only if** the value is still v0, i.e. not being changed at meantime. We can use `compute()` for CAS. If the attempt fails, i.e. the value is no longer v0 at the time, we'll loop again, read the current value, do computation, attempt to CAS, etc. The drawback of this approach is that it might become an infinite loop:) – ZhongYu Aug 16 '16 at 15:53
  • See this [example](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent/atomic/AtomicInteger.java#AtomicInteger.addAndGet%28int%29) of how atomic add *can* be implemented by CAS. – ZhongYu Aug 16 '16 at 15:57