简体   繁体   中英

Do I have to extend class to ConcurrentHashMap or can I have variable ConcurrentHashMap for threadSafety

I am creating Socket based Server-Client reservation service, and have problem about class which will be accessed by multiple threads, does it need to Extend ConcurrentHashMap or is it enough to create variable ConcurrentHashMap to be thread safe?

I have two ideas but I am not sure if first one will work, so the first one would be creating class which only implements Serializable has variable date and then variable ConcurrentHashMap on which threads want to operate, second idea is to have class which extends Concurrent Hash Map and just is CHP but with addiontal variable to make sure it is distinguishable from others

public class Day implements Serializable {
private LocalDate date;
private ConcurrentHashMap<String, Boolean> schedule;

public Day(LocalDate date){
    this.date = date;
    this.schedule = new ConcurrentHashMap<>();
    IntStream.range(10, 18).forEachOrdered(
            n -> this.schedule.put(LocalTime.of(n, 0).toString(), TRUE));
}

public void changeaval(String key,Boolean status) {
    this.schedule.replace(key,status);
}

public boolean aval(String key){
    return this.schedule.get(key);
}

public LocalDate getDate(){return this.date;}

public ConcurrentHashMap getSchedule(){return this.schedule;}

}

I just want to have Class/Object which can be accessed by multiple threads and can be distinguishable from others/comparable and has ConcurrentHashMap which maps Int -> Boolean This is the first time I am using Stack and It is my first project in Java so I don't know much sorry if something is not right.

There are basically two things to look out for when dealing with objects accessed by multiple threads:

  1. Race condition - Due to thread scheduling by the operating system and instruction reordering optimizations by the compiler, the instructions are executed in a order not intended by the programmer causing bugs
  2. Memory visibility - In a multi processor system, changes made by one processor is not always immediately visible to other processors. Processors keep things in their local registers and caches for performance reasons and therefore not visible to threads being executed by other processors.

Luckily we can handle both these situation using proper synchronizations.

Let's talk about this particular program.

Localdate by itself is an immutable and thread safe class. If we look at the source code of this class, we'd see that all the fields of this class are final . This means that as soon as the constructor of Localdate finishes initializing the object, the object itself will be visible across threads. But when it is assigned to a reference variable in a different object, whether the assignment (in other words, the content of the reference variable) would be visible to other threads or not is what we need to look out for.

Given the constructor in your case, we can ensure the visibility of the field date across threads provided date is either final or volatile . Since you are not modifying the date field in your class, you can very well make it final and that ensures safe initialization. If you later decide to have a setter method for this field (depending on your business logic and your design), you should make the field volatile instead of final . volatile creates a happens-before relationship which means that any instruction that is executed in the particular thread before writing to the volatile variable would be immediately visible to the other threads as soon as they read the same volatile variable.

Same goes for ConcurrentHashMap . You should make the field schedule final . Since ConcurrentHashMap by itself has all the necessary synchronizations in it, any value you set against a key would be visible to the other threads when they try to read it.

Note, however, that if you had some mutable objects as ConcurrentHashMap values instead of Boolean , you would have to design it in the same way as mentioned above.

Also, it may be good to know that there is a concept called piggy-backing which means that if one thread writes to all its fields and then writes to a volatile variable, everything written by the thread before writing to the volatile variable would be visible to the other threads, provided the other threads first read value of the volatile variable after it is written by the first thread. But when you do this you have to ensure very carefully the sequence of reading and writing and it is error prone. So, this is done when you want to squeeze out the last drop of performance from the piece of code which is rare. Favor safety, maintainability, readability before performance.

Finally, there is no race condition in the code. The only write that is happening is on the ConcurrentHashMap which is thread safe by itself.

Basically, both approaches are equivalent. From architectural point of view, making a variable inside dedicated class is preferred because of better control of which methods are accessible to the user. When extending, a user can access many methods of underlying ConcurrentHashMap and misuse them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM