Common problems one should consider while working with Multi threading
In today's world, hardware is getting advance. We have now hard disks which works fast enough to cope with RAM. We have very small small devices having so much capacity.
Similarly, in past few years, we are now living in multi core systems. We can have 16 core or even 32 cores machines running in production. So, as we have these many cores, we always try to work with multiple threads to increase the performance of the system.
Common problems with multi threading implementations
Shared resource compromised
While using multi threading, we often miss this aspect that there can be a chance that multiple threads will come in same critical section and may try to make changes. There are many good places where we can read about it. So, I am skipping this part in this article but just adding that any servlet (or related classes) also run by multiple threads (many tomcat threads).
Confusing with the concurrent classes usage
At times, it is also seen that people confuse with correct usage of concurrent classes. In one of the project recently while reviewing, I found some size calculation is done using ConcurrentHashMap. Key was some string and value was of Long type. The developer mistakenly calling following
Long data = map.get(key); //line 1
data += someIncrementValue; //line 2
map.put(key, data); //line 3
In above example, as we can see, the data in map will not always correctly increase data with some value as another thread may arrive at any time and may cause corruption of data.
Line1:
T1--> value found 0; T2--> value found 0
Line 2:
T1-->increase by 100; T2-->increase by 500
Line 3
T1--> puts 100; T2-->puts 500
Actual output should have been 600 but can be 100 or 500 depending on which one executed first.
Using cores blindly to create threads
In ideal scenario, if we have 4 cores, 4 threads which are working on computational tasks is sufficient number. But in case we have IO operation than this number can increase. Number of threads ideally should be used can be calculated here.
In, one of my project, I thought using such fancy formula and for every request I also calculated the number of threads using the formula and ran that many thread. All was good till we were working on 4 core machine. As soon as we moved to 8 core machine, we found our db connections are exhausted. The reason was that I used same logic in the method being called by the method already have that many threads created. For an instance, let us say, ideal number was n. So on 4 core machine I had 4 threads each of which trying to create 4 more threads. And worst happened in one of the flows where even these 4 * 4 threads were trying to create 4 more threads. As we were having connection pool of 50 only, so it become very difficult to handle such many threads.
So, this is one of the important aspect to be considered. While considering the number of threads for the system we must also ensure that they are used as for system only and not for a component or at least the component is not again creating that many threads. It is always better to switch to event based structure as mentioned in other article here.
We can also work on different such tasks using traffic-controller framework as mentioned at here. Sample code can be
@ Controlled(maxConsumer="5")
public void doSomeOperation() {...}
This will make sure that the method is run by only 5 threads at a given time. All threads will wait for their turn.