Questions about synchronization in java; when / how / to what extent

I am working on my first mutlithreaded program and fixated on several aspects of synchronization. I went over to the multi-threaded tutorial on the oracle / sun homepage, as well as a number of questions here on SO, so I think I have an idea of ​​what synchronization is. However, as I mentioned, there are several aspects, I’m not quite sure how to understand this. I formulated them below as a clear question:

Question 1: I have a singleton class that contains methods for checking valid identifiers. It turns out that this class needs to be stored in collections in order to track associations between two different types of identifiers. (If the word identifier sounds more complicated, it's just a string). I decided to implement two instances of MultiValueMap to implement this many-to-many relationship. I'm not sure that these collections should be thread safe, since the collection will only be updated when instantiating a singleton class, but nonetheless I noticed that the documentation says:

Please note that MultiValueMap is not synchronized and is not thread safe. If you want to use this card from several streams at the same time, you should use appropriate synchronization. This class may throw exceptions when accessed by parallel threads without synchronization.

Can anyone clarify this “appropriate synchronization”? What exactly does this mean? Can't I use MultiValueMap.decorate() for a synchronized HashMap , or am I misunderstanding something?

Question 2: I have another class that extends HashMap to store my experimental values, which are analyzed when the software starts. This class is intended to provide suitable methods for my analysis, such as permutation() , randomization() , filtering(criteria) , etc. Since I want to protect my data as much as possible, the class is created and updated once, and all of the above methods return new collections. Again, I am not sure that this class should be thread safe, since it should not be updated from multiple threads, but the methods will certainly be called from multiple threads, and to be "safe", I added synchronized for all my methods. Can you anticipate any problems with this? What potential problems should I know?

Thanks,

+3
source share
4 answers

Answer 1:. Your singleton class should not expose the collections it uses internally to other objects. Instead, it should provide appropriate methods to identify the behavior you want. For example, if your object has a Map , it does not have a public or protected method for returning this Map . Instead, there is a method that takes the key and returns the corresponding value in Map (and possibly the one that sets the value for the key). These methods can then be made thread safe if necessary.

NB, even for collections that you are not going to write to, I do not think that you should assume that reading is necessarily thread safe if they are not documented like that. A collection object can maintain some internal state that you do not see, but can be changed when reading.

Answer 2: First, I do not think that inheritance is necessarily the right thing to use here. I would have a class that provides your methods and has a HashMap as a private member. As long as your methods do not change the internal state of the object or HashMap, they do not need to be synchronized.

+2
source

It’s hard to give general rules about synchronization, but your general understanding is correct. The data structure used in read-only mode does not need to be synchronized. But, (1) you must ensure that no one (i.e. no other thread) can use this structure before it is properly initialized, and (2) that the structure is really read-only. Remember that even iterators have a delete method.

To your second question: to ensure immutability, that is, to read read-only, I would not inherit the HashMap, but use it inside your class.

+2
source

If your cards are filled once, while the class is loading (i.e. into the static initializer block) and never changes after that (i.e. no elements or associations are added / removed), you're fine. Static initialization is guaranteed by the JVM to be a safe thread, and its results are visible to all threads. Thus, in this case, you most likely will no longer need synchronization.

If the cards are members of the instance (this is not clear to me from your description), but were not changed after creation, I would say that you are most likely to be safe if you declare your members final (if you do not publish this object prematurely, i.e., pass it to the outside world from the cunstructor somehow before the completion of the constructor).

+1
source

Synchronization is usually necessary when you can either have parallel modifications to the underlying data, or one thread modifies the data, and the other reads and needs to see this modification.

In your case, if I understand it correctly, the MultiValueMap is populated once upon creation and just read. Therefore, if reading the card does not lead to a change in some internal elements, it should be safe to read it from multiple streams without synchronization. The creation process must be synchronized, or you should at least prevent read access during initialization (a simple flag is enough).

The class that you can ask in question 2 may not need to be synchronized if you always return new collections, and the internal elements of the base collection do not change when you create these “copies”.

One more note: note that values ​​in collections can also be synchronized, because if you reliably receive an object from a collection in several threads, but then change this object at the same time, you will still get problems.

As a general rule: read-only access does not necessarily require synchronization (if the objects do not change during these readings or if it does not matter), write access should usually be synchronized.

+1
source

Source: https://habr.com/ru/post/1343019/


All Articles