Java java.util.ConcurrentModificationException error - java

please can anybody help me solve this problem last so many days I could not able to solve this error. I tried using synchronized method and other ways but did not work so please help me
Error
java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.remove(Unknown Source)
at JCA.startAnalysis(JCA.java:103)
at PrgMain2.doPost(PrgMain2.java:235)
Code
public synchronized void startAnalysis() {
//set Starting centroid positions - Start of Step 1
setInitialCentroids();
Iterator<DataPoint> n = mDataPoints.iterator();
//assign DataPoint to clusters
loop1:
while (true) {
for (Cluster c : clusters)
{
c.addDataPoint(n.next());
if (!n.hasNext())
break loop1;
}
}
//calculate E for all the clusters
calcSWCSS();
//recalculate Cluster centroids - Start of Step 2
for (Cluster c : clusters) {
c.getCentroid().calcCentroid();
}
//recalculate E for all the clusters
calcSWCSS();
// List copy = new ArrayList(originalList);
//synchronized (c) {
for (int i = 0; i < miter; i++) {
//enter the loop for cluster 1
for (Cluster c : clusters) {
for (Iterator<DataPoint> k = c.getDataPoints().iterator(); k.hasNext(); ) {
// synchronized (k) {
DataPoint dp = k.next();
System.out.println("Value of DP" +dp);
//pick the first element of the first cluster
//get the current Euclidean distance
double tempEuDt = dp.getCurrentEuDt();
Cluster tempCluster = null;
boolean matchFoundFlag = false;
//call testEuclidean distance for all clusters
for (Cluster d : clusters) {
//if testEuclidean < currentEuclidean then
if (tempEuDt > dp.testEuclideanDistance(d.getCentroid())) {
tempEuDt = dp.testEuclideanDistance(d.getCentroid());
tempCluster = d;
matchFoundFlag = true;
}
//if statement - Check whether the Last EuDt is > Present EuDt
}
//for variable 'd' - Looping between different Clusters for matching a Data Point.
//add DataPoint to the cluster and calcSWCSS
if (matchFoundFlag) {
tempCluster.addDataPoint(dp);
//k.notify();
// if(k.hasNext())
k.remove();
for (Cluster d : clusters) {
d.getCentroid().calcCentroid();
}
//for variable 'd' - Recalculating centroids for all Clusters
calcSWCSS();
}
//if statement - A Data Point is eligible for transfer between Clusters.
// }// syn
}
//for variable 'k' - Looping through all Data Points of the current Cluster.
}//for variable 'c' - Looping through all the Clusters.
}//for variable 'i' - Number of iterations.
// syn
}

You can't modify a list while you're iterating it, unless you do it through the Iterator.
From the API: ConcurrentModificationException
This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.
For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it.
Your code is a mess, so it's hard to figure out what's going on, but I'd check for:
Shared references
All remove AND add

I think that simply looking up the javadoc for ConcurrentModificationException would have answered your question. Did you try that?
Iterator.remove() is causing the exception, presumably on the linke k.remove(). This means you modified the List it is iterating over while iterating, which is not allowed. So you need to figure out where c.getDataPoints() is changing. I am guessing it is because you eventually find a cluster d, assign to tempCluster, then change its data points (which is eventually the list you are iterating over.

if you need to delete few elements from your list. You can maintain another list like elements to be removed. And finally call removeAll(collection). Of course this is not good for huge data.

Keep few things in mind to avoid concurrent access issues :
First of all the method (startAnalysis) is an instance method. So synchronization will be specific to its instance. So you need to make sure that all the threads trying to access this method must use the same instance to avoid concurrent access issues. If every thread is referring to a different instance, then all the threads will be allowed to execute the method and eventually may lead to concurrency issues.
Secondly, one should always prefer to use Iterator rather the for:each loop to iterate over collections, to avoid concurrent access/modification issues.
Also you can use concurrent collection api classes to avoid concurrency issues. These classes are heavily used in such requirements to avoid concurrent modification issues.
Hope this helps.

Related

Java Recursive function sometimes working

I've called upon what I've learned so far and still can't fix this so decided to come here.
A BasicBlock object is referenced by an integer and holds references to the 'addresses' of more blocks in a list. I want to obtain the addresses that they hold reference to and i thought to do this recursively. It is possible for one BasicBlock to hold reference to 0 or more other blocks.
The below recursive function getFunctionReferences keeps returning a stack overflow error, yet manages to work sometimes.
Map<Integer,BasicBlock> blockList blockList = new TreeMap<Integer,BasicBlock>();
public HashSet<Integer> getAssociatedAddresses(int function) {
HashSet<Integer> blockAddresses = new HashSet<Integer>();
getFunctionReferences(this.blockList.get(function),blockAddresses);
return blockAddresses;
}
private void getFunctionReferences(BasicBlock block, HashSet<Integer> blockAddresses){
for (int x : block.getAddressReferenceList()) {
blockAddresses.add(x);
getFunctionReferences(this.blockList.get(x), blockAddresses);
}
}
I know that I am doing something wrong with this call, especially as there is no base case. But I don't know how to deal with recursion when it is in a loop like this....nor do I know a suitable base case.
Help massively appreciated.
Thanks
If you have cycles (for example block 1 references block 2 which references block 3 which references block 1), you'll get infinite recursion leading to StackOverflowError.
To avoid that, you can take advantage of the HashSet of visited blocks which you maintain. You can simply check if a block was already visited and avoid making another recursive call if it was:
private void getFunctionReferences(BasicBlock block, HashSet<Integer> blockAddresses){
for (int x : block.getAddressReferenceList()) {
if (blockAddresses.add(x)) { // only make a recursive call if x wasn't already
// in the Set
getFunctionReferences(this.blockList.get(x), blockAddresses);
}
}
}

Java : Is the get method of an Arraylist cached?

Does the Arraylist object store the last requested value in memory to access it faster the next time? Or do I need to do this myself?
Or more concretely, in terms of performance, is it better to do this :
for (int i = 0; i < myArray.size(); i++){
int value = myArray.get(i);
int result = value + 2 * value - 5 / value;
}
Instead of doing this :
for (int i = 0; i < myArray.size(); i++)
int result = myArray.get(i) + 2 * myArray.get(i) - 5 / myArray.get(i);
In terms of performance, it doesn't matter one bit. No, ArrayList doesn't cache anything, although the JITted end result could be a different issue.
If you're wondering which version to use, use the first one. It's clearer.
You can answer your (first) question yourself by looking into the actual source:
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
So: No, there is no caching taking place but you can also see that there is no much of an impact in terms of performance because the get method is essentially just an access to an array.
But it's still good to avoid multiple calls for some reasons:
int result = value + 2 * value - 5 / value is easier to understand (i.e. realizing that you use the same value three times in your calculation)
If you later decide to change the underlying list (e.g. to a LinkedList) you might end up with an impact on performance and then have to change your code to get around it.
As long as you don't synchronize the access to the list, repeated calls of get(index) might actually return different values if between two calls a call of set(index, value) has taken place (even in small souce blocks like this, it's possible to happen - BTST)
The second point has also a consequence in terms of how to access all values of a list, that leads to the decision to avoid list.get(i) altogether if you're going to iterate over all elements in a list. In that case it's better to use the Iterator or streams:
You code would then look like this:
Iterator it = myArray.iterator();
while (it.hasNext()) {
int value = it.next();
int result = value + 2 * value - 5 / value;
}
LinkedList is very slow when trying to access elements in it by specific index but can iteratre quite fast from one element to the next, so the Iterator returned by LinkedList makes use of that while the Iterator returned by ArrayList simply accesses the internal array (without the need to do the repeated range check calls you can see in the get-method above

Java is not assigning values to my variables correctly, with linked lists

public void returnRental(Customer cust){
Rental toDelete = null; //Rental to be removed from list.
LinkedList<Video> toReturn = null; //List of videos to be added to inventory.
//Find appropriate rental according to customer name.
for(int i = 0; i < rentals.size(); i++){
if(cust.getName() == rentals.get(i).getRentee().getName()){
toReturn = rentals.get(i).getRented();
toDelete = rentals.get(i);
}
}
here is the snippet of code that is giving me problems. I've debugged it in eclipse quite a bit which ended up just confusing me more. It hits the if, and passes the condition. But once it gets to assigning values to "toReturn" it assigns it an empty list with size 0. Where as I check my rentals Linked list and the correct value are there, but for some reason it is not getting assigned to my variables correctly :( The same happens to "toDelete" but this isn't a list, it is one instance of my class Rental. (The linked list is a list of rentals, which contains a linked list of videos)
No errors are thrown...
Its a little difficult to explain, if you need more information please let me know and i'll clarify.
I'm at a loss, possibly because I'm not iterating through my linked list correctly?
Replace
if (cust.getName() == rentals.get(i).getRentee().getName()){
by
if (cust.getName().equals(rentals.get(i).getRentee().getName())){
You can't compare strings with == (except if your algorithm can ensure this is the same instance, which is almost never the case).
But the missing equals is not the only bug. It may be inside getRented() or elsewhere (you don't show what you do with toReturn and toDelete, so it's not clear if you don't have problems here).
Now, to go on chasing your bugs, you should either
debug, and put a breakpoint in your loop to check the state of rentals.get(i) and the execution at this point
if you can't debug, put a lot of System.println, so that you know what you have...
I've upvoted dystroy's answer because incorrect string comparison is always wrong.
But because that would fail differently (customer names not matching rentee names), I'm wondering if your issue is really caused by either of the following:
a problem in getRented(); or
cust having a null name on call, which would match a Rentee with a null name.
Possibly, your if condition is being hit more than once. First of all, check if this is actually happening. If so, check your logic and determine if you want to stop at the first occurence or at the last (this case seems to be the latter).
If you want to stop at the first occurence, break the iteration:
for(int i = 0; i < rentals.size(); i++){
if(cust.getName() == rentals.get(i).getRentee().getName()){
toReturn = rentals.get(i).getRented();
toDelete = rentals.get(i);
break;
}
}
for(int i = 0; i < rentals.size(); i++){
if(cust.getName().equals( rentals.get(i).getRentee().getName())){
toReturn.addAll(rentals.get(i).getRented());
//assumming it returns the list of Video object
toDelete = rentals.get(i);
}
}

Updating both a ConcurrentHashMap and an AtomicInteger safely

I have to store words and their corresponding integer indices in a hash map. The hash map will be updated concurrently.
For example: lets say the wordList is {a,b,c,a,d,e,a,d,e,b}
The the hash map will contain the following key-value pairs
a:1
b:2
c:3
d:4
e:5
The code for this is as follows:
public class Dictionary {
private ConcurrentMap<String, Integer> wordToIndex;
private AtomicInteger maxIndex;
public Dictionary( int startFrom ) {
wordToIndex = new ConcurrentHashMap<String, Integer>();
this.maxIndex = new AtomicInteger(startFrom);
}
public void insertAndComputeIndices( List<String> words ) {
Integer index;
//iterate over the list of words
for ( String word : words ) {
// check if the word exists in the Map
// if it does not exist, increment the maxIndex and put it in the
// Map if it is still absent
// set the maxIndex to the newly inserted index
if (!wordToIndex.containsKey(word)) {
index = maxIndex.incrementAndGet();
index = wordToIndex.putIfAbsent(word, index);
if (index != null)
maxIndex.set(index);
}
}
}
My question is whether the above class is thread safe or not?
Basically an atomic operation in this case should be to increment the maxIndex and then put the word in the hash map if it is absent.
Is there a better way to achieve concurrency in this situation?
Clearly another thread can see maxIndex incrementing and then getting clobbered.
Assuming this is all that is going on to the map (in particular, no removes), then you could try putting the word in the map and only incrementing if that succeeds.
Integer oldIndex = wordToIndex.putIfAbsent(word, -1);
if (oldIndex == null) {
wordToIndex.put(word, maxIndex.incrementAndGet());
}
(Alternatively for a single put, use some sort of mutable type in place of Integer.)
No, it is not. If you have two methods A and B, both thread safe, this of course does not mean that calling A and B in a sequence is also thread safe, as a thread can interrupt another one between the function calls. This is what happens here:
if (!wordToIndex.containsKey(word)) {
index = maxIndex.incrementAndGet();
index = wordToIndex.putIfAbsent(word, index);
if (index != null)
maxIndex.set(index);
}
Thread A verifies that wordToIndex does not contain the word "dog" and proceeds inside the if. Before it can add the word "dog", thread B also finds that "dog" is not in the map (A did not add it yet) so it also proceeds inside the if. Now you have the word "dog" trying to be inserted twice.
Of course, putIfAbsent will guarantee that only one thread can add it, but I think that your goal is to not have two threads enter the if at the same time with the same key.
AtomicInteger is something you should consider using.
And you should wrap all the code that needs to happen as a transaction in a synchronized(this) block.
The other answers are correct --- there are non-thread-safe fields in your class. What you should do, to start, is make sure
how to implement the threading
1) I would make sure everything internal is private, although this is not a requirement of thread-safe code.
2) Find any of your accessor methods, make sure they are snychronized whenever the state of the global object is modified (OR AT LEAST THE IF BLOCK IS SYNCHRONIZED).
3) Test for deadlocks or bad counts, this can be implemented in a unit test by making sure the value of maxIndex is correct after 10000 threaded inserts, for example...

ConcurrentWeakKeyHashMap isEmpty method

The following is isEmpty() method from ConcurrentWeakKeyHashMap.java,
https://github.com/netty/netty/blob/master/src/main/java/org/jboss/netty/util/internal/ConcurrentWeakKeyHashMap.java
Why does it need mcsum, and what does the if(mcsum!= 0) {..} block doing ?
And more importantly, how do I get
if (segments[i].count != 0 || mc[i] != segments[i].modCount)
to evaluate to true?
public boolean isEmpty() {
final Segment<K, V>[] segments = this.segments;
/*
* We keep track of per-segment modCounts to avoid ABA problems in which
* an element in one segment was added and in another removed during
* traversal, in which case the table was never actually empty at any
* point. Note the similar use of modCounts in the size() and
* containsValue() methods, which are the only other methods also
* susceptible to ABA problems.
*/
int[] mc = new int[segments.length];
int mcsum = 0;
for (int i = 0; i < segments.length; ++ i) {
if (segments[i].count != 0) {
return false;
} else {
mcsum += mc[i] = segments[i].modCount;
}
}
// If mcsum happens to be zero, then we know we got a snapshot before
// any modifications at all were made. This is probably common enough
// to bother tracking.
if (mcsum != 0) {
for (int i = 0; i < segments.length; ++ i) {
if (segments[i].count != 0 || mc[i] != segments[i].modCount) {
return false;
}
}
}
return true;
}
EDIT:
Code to evaluate the above if block is now in ConcurrentWeakKeyHashMapTest
Essentially 1 thread continously monitors the concurrentMap, while another thread continuously add/remove same keypair value
This method is a copy of the same in Javas ConcurrentHashMap.
This kind of Map is using a modCount per segment to track during operations if it remained unchanged by different treads. During our traversal of the Map there could actually be other operations modifying the Map. This is called an ABA problem. We are asking the Map if it is empty and in fact it is not, but by accident it appears to be. A simple example:
Map with three segements
Segment 1: size=0
Segment 2: size=0
Segment 3: size=1
In this moment we decide to ask the Map and look into segment 1, which appears to be empty.
Now another algorithm comes and inserts an element to segment 1, but removes the other from segment 3. The Map was never empty.
Our Thread is running now again and we look into segment 2 and 3, both are empty. For us the Map is empty - as a result.
But for any empty slot we tracked whether it was modified, too. And for slot 3 we realize there have been modifications: mc[2]>=1 which means mcsum>=1. This means: since construction the Map was modified at least once. So to answer what mcsum is for: It is a shortcut for the default empty ConcurrentHashMap. If there never have been modifications, we do not need to check for concurrent modifications.
So we know something happened and check again each segment. If now a segment is empty we know what its modCount has been. For segment 3, lets say it was 1, for segment 1 it has been 0. Checking the modCount of segment 1 now it is 1 and the count is > 0 so we know that the Map is not empty.
Still there could be an ABA problem in the second loop as well. But because we know the modCounts we can catch any other concurrent algorithm changing something. So we say if the segment is empty and something changed with the modCount it has not been empty in the first place. That is, what the second loop is doing.
Hope this helps.
EDIT
And more importantly, how do I get
if (segments[i].count != 0 || mc[i] != segments[i].modCount)
to evaluate to true?
This evaluates to true if a segment contains something or if something was modified since the first loop. And it evaluates to false (which means: segment empty) if the segment contains nothing AND nothing was changed since the first loop. Or, to say it differently: We can be sure it has been empty all the time since looked on the checked segment first.
The mcsum checks if the map has ever been structurally modified. There appears to be no way to reset the modification counts to zero, so if the map has ever contained anything at all mcsum will be non-zero.
The weak keys are only cleaned up when the map is changed through a put, remove, et c, and they are only cleaned up within the modified segment. Retrieving values from the map does not clear up the weak keys. This means the map as implemented will hold many weak keys that have been garbage collected as they are only cleaned up if the same segment is modified.
This means results from the size() and isEmpty() methods will frequently return the wrong result.
With the API as provided your best recourse is to call purgeStaleEntries() prior to checking if the map is empty.

Categories