Andrey Sapegin
Andrey Sapegin

Reputation: 484

threads accessing non-synchronised methods in Java

can I ask to explain me how threads and synchronisation works in Java?

I want to write a high-performance application. Inside this application, I read a data from files into some nested classes, which are basically a nut-shell around HashMap.

After the data reading is finished, I start threads which need to go through the data and perform different checks on it. However, threads never change the data!

If I can guarantee (or at least try to guarantee;) that my threads never change the data, can I use them calling non-synchronised methods of objects containing data?

If multiple threads access the non-synchronised method, which does not change any class field, but has some internal variables, is it safe?

artificial example:

public class Data{
// this hash map is filled before I start threads
protected Map<Integer, Spike> allSpikes = new HashMap<Integer, Spike>();

public HashMap returnBigSpikes(){
     Map<Integer, Spike> bigSpikes = new HashMap<Integer, Spike>();

     for (Integer i: allSpikes.keySet()){
         if (allSpikes.get(i).spikeSize > 100){
         bigSpikes.put(i,allSpikes.get(i));
         }
     }

     return bigSpikes;
}
}

Is it safe to call a NON-synchronised method returnBigSpikes() from threads?

I understand now that such use-cases are potentially very dangerous, because it's hard to control, that data (e.g., returned bigSpikes) will not be modified. But I have already implemented and tested it like this and want to know if I can use results of my application now, and change the architecture later...

What happens if I make the methods synchronised? Will be the application slowed down to 1 CPU performance? If so, how can I design it correctly and keep the performance?

(I read about 20-40 Gb of data (log messages) into the main memory and then run threads, which need to go through the all data to find some correlation in it; each thread becomes only a part of messages to analyse; but for the analysis, the thread should compare each message from its part with many other messages from data; that's why I first decided to allow threads to read data without synchronisation).

Thank You very much in advance.

Upvotes: 0

Views: 281

Answers (6)

Chrstian Beutenmueller
Chrstian Beutenmueller

Reputation: 807

As long as anything practically immutable (eg. using final keyword) and you use an unmodifiableMap everything is fine.

I would suggest the following UnmodifiableData:

public class UnmodifiableData {
     final Map<Integer,Spike>  bigSpikes;
     public UnmodifiableData(Map<Integer,Spike> bigSpikes) {
         this.bigSpikes = Collections.unmodifiableMap(new HashMap<>(bigSpikes));
     }
     ....

}

Upvotes: 1

Rich
Rich

Reputation: 46

In general, if you have a bunch of threads where you can guarantee that only one thread will modify a resource and the rest will only read that resource, then access to that resource doesn't need to be synchronised. In your example, each time the method returnBigSpikes() is invoked it creates a new local copy of bigSpikes hashmap, so although you're creating a hashmap it is unique to each thread, so no sync'ing problems there.

Upvotes: 1

Evgeniy Dorofeev
Evgeniy Dorofeev

Reputation: 136012

Since allSpikes is initialized before you start threads it's safe. Concurrency problems appear only when a thread writes to a resource and others read from it.

Upvotes: 0

Keppil
Keppil

Reputation: 46219

If allSpikes is populated before all the threads start, you could make sure it isn't changed later by saving it as an unmodifiable map.

Assuming Spike is immutable, your method would then be perfectly safe to use concurrently.

Upvotes: 3

Mikhail
Mikhail

Reputation: 4223

If you use ConcurrentHashMap, it will do all syncronization work for you. Its bettr, then making synronization around ordinary HashMap.

Upvotes: 0

OldCurmudgeon
OldCurmudgeon

Reputation: 65811

Your plan should work fine. You do not need to synchronize reads, only writes.

If, however, in the future you wish to cache bigSpikes so that all threads get the same map then you need to be more careful about synchronisation.

Upvotes: 0

Related Questions