Is it possible to solve this code without keyword synchronized?
Can we use ConcurrentHashMap or better HashMap with synchronized keyword (for methods)?
Or better ConcurrentHashMap (for iterating) with synchronized keyword (for methods)?
This is critical section code, reader thread get statistic and when decrement value (if value is zero, remove statistic but parallel writer thread may incement value). How to properly solve this?
Statistic statistic = data.get(id);
if (statistic != null) {
statistic.dec();
if (statistic.getValue() <= 0) {
data.remove(id);
}
public class Main {
private static final Map<Long, Statistic> data = new ConcurrentHashMap<>();
public static void main(String... args) throws IOException {
new Thread(() -> todoRunInWriterThread(1L)).start();
new Thread(() -> todoRunInReaderThread(1L)).start();
System.in.read();
}
//Many writers write some statistics
private static void todoRunInWriterThread(long id) {
Statistic statistic = data.get(id);
if (statistic == null) {
statistic = new Statistic();
data.put(id, statistic);
}
statistic.inc();
}
//Many readers read statistic and decrement value,
//if statistic value is zero (remove statistic)
private static void todoRunInReaderThread(long id) {
Statistic statistic = data.get(id);
if (statistic != null) {
statistic.dec();
if (statistic.getValue() <= 0) {
data.remove(id);
}
}
}
public static class Statistic {
private AtomicLong value = new AtomicLong(0);
public long getValue() {
return value.longValue();
}
public void inc() {
value.incrementAndGet();
}
public void dec() {
value.decrementAndGet();
}
}
}
I believe you should use ConcurrentHashMap. It has good performance in most cases, and your case for writer thread (get ... check if null ... put) can be resolved with ConcurrentHashMap#computeIfAbsent -> it will handle all locking internally.
Also please do some research about how ConcurrentHashMap works. it's not simply using synchronized keyword for each method. There's some striping locking involved, which is really good for performance