• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Bear Bibeault
  • Junilu Lacar
Sheriffs:
  • Jeanne Boyarsky
  • Tim Cooke
  • Henry Wong
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • salvin francis
  • Frits Walraven
Bartenders:
  • Scott Selikoff
  • Piet Souris
  • Carey Brown

Can this snippet produce ConcurrentModification Exception.

 
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,
My application is throwing ConcurrentModificationException but I am not able to figure out the reason behind that.Any pointers would help.
My Code is similar to below Test Class



In the logs I see ConcurrentModificationException at line the point where .put is being called.

Can call to init() throw Exception in MultiThreaded Environment when call to init() is made using
a) different objects of Test
b) same object of Test
c) any other possible way this can happen.

If yes,
how do I prevent it.

Thanks
 
Bartender
Posts: 3648
16
Mac OS X Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You are looping/reading the map AND modifying/writing to it at the same time. HashMap is not a concurrent collection. Similarly if you use an ArrayList instead of HashMap, the same ConcurrentModificatioException will occur. This exception also occur if you loop and remove elements from collection.

The concurrent version is java.util.concurrent.ConcurrentHashMap.
 
Ankur Luthra
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you for your reply.
So if I change my HashMap to ConcurrentHashMap .It should solve the problem .right?

Also will the below solution solve the issue






 
Ankur Luthra
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just to clarify my understanding

This can only happen if different Threads are calling init using two different objects of Test classe right?

As per my understanding.
If init() is called by two different Threads using the same instance, because of synchronized on init() method ,second thread will have to wait to gain access to init() method.

Please correct me if I am wrong.
 
K. Tsang
Bartender
Posts: 3648
16
Mac OS X Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Using ConcurrentHashMap will solve your problem (at least will not throw ConcurrentModificatioException).

As for synchronizing the method or block using a HashMap will not help. Synchronizing is for multiple user access. But your scenario is collection access. It's like thread A holds a lock read data and thread B comes along "waiting" to write data but can't, forever.... deadlock or is it starvation. But the API is smart enough to let you know by throwing exception
 
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First, it is a very bad practice to access static variables inside a non static method in a multi-threaded application. Is that something you can change?

While one of your thread might be creating the map/putting elements into your map, it might already be in an inconsistent state. Also your String might have been changed.

There are many other circumstances in which ConcurrentModificationException can be thrown. And you might want to read about them in the Oracle docs.

HIH.
Chan.
 
K. Tsang
Bartender
Posts: 3648
16
Mac OS X Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Ankur Luthra wrote:If init() is called by two different Threads using the same instance, because of synchronized on init() method ,second thread will have to wait to gain access to init() method.



Yes this is true because of the synchronize keyword. In each thread, a new instance of the map is created because you put the "new XXXMap(testStr.length)" inside the synchronized block.
 
Ankur Luthra
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Chan for your response.
I am afraid, I cant change that i.e. use of static inside non-static method.

Could you please elaborate on your below statement.

Chan Ag wrote:
While one of your thread might be creating another local HashMap from your static map, it might be in an inconsistent state. You should fix that.



 
K. Tsang
Bartender
Posts: 3648
16
Mac OS X Firefox Browser Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think what Chan meant was to do something like:

 
Chan Ag
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Chan Ag wrote:

While one of your thread might be creating another local HashMap from your static map, it might be in an inconsistent state. You should fix that.



Hey, sorry about that. I didn't see properly that there was no local map.

What I meant is this.
While one of your thread might be creating the map/putting elements into your map, it might already be in an inconsistent state. Also your String array might have been changed.


I've just edited it but because I type very slowly, my post is almost always 'preempted' by other posts. :-)

Are you able to follow now or did I end in confusing you more. I can start over and give it a second try.

Chan.

 
Ankur Luthra
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

K. Tsang wrote:I think what Chan meant was to do something like:



I can't make this variable as local to init() method so lets rule out this option. :-)
 
Chan Ag
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Let me explain.

There are two kinds of fields and methods. Static and instance methods. Static fields/methods are a part of Class object associated with every class.

When we synchronize an instance method, we are protecting the instance specific fields and methods only. When we synchronize a static method, we acquire a lock on the class object and we are protecting the static fields/methods.

While a thread is executing inside a synchronized instance method, other threads accessing the same object cannot access other synchronized instance methods but they can access the static synchronized/non synchronized methods. Similarly when a thread is executing a synchronized static method, other threads can access synchronized as well as not synchronized instance methods concurrently.

In your case, you have a static HashMap and a static String array. And I guess you need to protect them from concurrent modifications. But the init method is an instance method. It is only protecting the instance fields and methods. Now do you see where there is a problem?

Try to come up with a solution on how you'd fix that.

Chan.



 
Ankur Luthra
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
NA
 
Ankur Luthra
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Chan Ag wrote:

What I meant is this.
While one of your thread might be creating the map/putting elements into your map, it might already be in an inconsistent state. Also your String array might have been changed.
Chan.



I didn't get the above part..can you explain on this.

Please suggest If I am correct on below point or not
a) If multiple threads are accessing init() method using the same instance of Test, this problem would never occur.Because at one time one thread will have access to synchronized method init().
When one thread completes other thread would create a new Object and start writing again.So no issues here right?


b)If multiple threads are accessing init() method using the different instance of Test ,this problem could occur.

let me know if I am wrong in understanding .
I need to first of all understand which of the above scenarios can cause this.

I am using below program to try and simulate this


 
Ankur Luthra
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Chan Ag wrote:

In your case, you have a static HashMap and a static String array. And I guess you need to protect them from concurrent modifications. But the init method is an instance method. It is only protecting the instance fields and methods. Now do you see where there is a problem?



Thank you for your time Chan.

If you see the Test class ,the static Map is used inside synchronized instance method init().So if two threads try to call this method using the same object they can never enter together .One has to wait for other to leave and the only place this object is modified is inside this synchronized instance method.

So can we rule out the situation when this method is called using same instance of Test Class.?

The only case when this exception could occur is when two threads try to call init() method using different instances of Test .Right?
 
Chan Ag
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

If you see the Test class ,the static Map is used inside synchronized instance method init().So if two threads try to call this method using the same object they can never enter together .One has to wait for other to leave and the only place this object is modified is inside this synchronized instance method.

So can we rule out the situation when this method is called using same instance of Test Class.?

The only case when this exception could occur is when two threads try to call init() method using different instances of Test .Right?



That would be right given what you said.

But I'm wondering why are you doing what you are doing? Did you intend to call the init method only once? If yes, you are clearly not doing that.

If you intend to call the init method multiple times, why are you recreating the static map from a static array?

Chan.
 
Chan Ag
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
How about we begin with you stating your requirement clearly so people might be able to suggest better.

 
Ankur Luthra
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Chan Ag wrote:

If you see the Test class ,the static Map is used inside synchronized instance method init().So if two threads try to call this method using the same object they can never enter together .One has to wait for other to leave and the only place this object is modified is inside this synchronized instance method.

So can we rule out the situation when this method is called using same instance of Test Class.?

The only case when this exception could occur is when two threads try to call init() method using different instances of Test .Right?



That would be right given what you said.

But I'm wondering why are you doing what you are doing? Did you intend to call the init method only once? If yes, you are clearly not doing that.

If you intend to call the init method multiple times, why are you recreating the static map from a static array?

Chan.




Init() can called one time by multiple Threads using different instances of Test Class. I get your point that in every Thread ,code is recreating the static HashMap.

So if I initialize the HashMap it in the beginning ,do you think issue will not occur.

i.e. something like,



Here also one Thread may try to access the HashMap and other is putting into the Map ,but because the keys(testStr[i]) are same ,so ideally no modification of Collection is happening.
Can you may be suggest how can I make safe from Exception.One way suggested was making Map to ConcurrentHashMap.
 
Ankur Luthra
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Chan Ag wrote:How about we begin with you stating your requirement clearly so people might be able to suggest better.



My requirement is to call init method.
I need to somehow have this Map populated with key as testStr[i] and value as new Integer(0) in the method.

a) This method can be called by multiple threads one time using the same instance of Test class.
b) This method can be called by multiple threads one time using the different instances of Test class.

Can i get this population of Map somehow Thread Safe?
 
Chan Ag
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Init() can called one time by multiple Threads using different instances of Test Class. I get your point that in every Thread ,code is recreating the static HashMap.

So if I initialize the HashMap it in the beginning ,do you think issue will not occur.

i.e. something like, ................................



Like I said, forget about the ConcurrentModificationException now. There are many basic things that we may need fix here. They are easy to understand but let's do it one step at a time.

So like I said before, what is your requirement. Not how many threads, how many objects and stuff.. but what you want to do.

Like - 'I want to create a map that contains some key value pairs. This map needs to be accessible by all objects of my class. But I need to initialize the map only once. .. and stuff.. '
I'm not sure though if that is your requirement.

But, if you do this-

Init() can called one time by multiple Threads using different instances of Test Class.



Do you realize what you're doing when each of your thread is attempting to ( let's imagine there was no ConcurrentModificationException ) re-create a similar map in every invocation. Even if your init method was a static method, wouldn't that be a pointless thing to do?

So like I said, come up with reasons on why you're doing what you are doing.

Chan.

 
Ankur Luthra
Ranch Hand
Posts: 39
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Chan Ag wrote:

Init() can called one time by multiple Threads using different instances of Test Class. I get your point that in every Thread ,code is recreating the static HashMap.

So if I initialize the HashMap it in the beginning ,do you think issue will not occur.

i.e. something like, ................................



Like I said, forget about the ConcurrentModificationException now. There are many basic things that we may need fix here. They are easy to understand but let's do it one step at a time.

So like I said before, what is your requirement. Not how many threads, how many objects and stuff.. but what you want to do.

Like - 'I want to create a map that contains some key value pairs. This map needs to be accessible by all objects of my class. But I need to initialize the map only once. .. and stuff.. '
I'm not sure though if that is your requirement.

But, if you do this-

Init() can called one time by multiple Threads using different instances of Test Class.



Do you realize what you're doing when each of your thread is attempting to ( let's imagine there was no ConcurrentModificationException ) re-create a similar map in every invocation. Even if your init method was a static method, wouldn't that be a pointless thing to do?

So like I said, come up with reasons on why you're doing what you are doing.

Chan.



Chan I agree with every thing you said above.
I didn't write the code but have been given the dirty work of finding out what could be going wrong with the code.
This is the exact requirement that you mentioned above
"I want to create a map that contains some key value pairs. This map needs to be accessible by all objects of my class. But I need to initialize the map only once. .. and stuff.. '" and I know its pointless to re create similar Map fir every Thread invocation but wanted to fix this without shuffling code much.

How about initializing in the Static block.

 
Chan Ag
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm signing off for the day cause I need to get back to my assignments. There are other nicer, wiser people around and I'm sure they'll help you. But you might want to give a thought to the things I said.

Take a break of at least some 15-20 minutes before posting again. :-) And in that period, reflect on your requirement. You might get a deeper understanding of it by doing that.

I'm sure you will be able to solve things yourself/or with minimal additional help.

Chan.



 
Ankur Luthra
Ranch Hand
Posts: 39
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Chan Ag wrote:I'm signing off for the day cause I need to get back to my assignments. There are other nicer, wiser people around and I'm sure they'll help you. But you might want to give a thought to the things I said.

Take a break of at least some 15-20 minutes before posting again. :-) And in that period, reflect on your requirement. You might get a deeper understanding of it by doing that.

I'm sure you will be able to solve things yourself/or with minimal additional help.

Chan.




Thanks Chan for all your time.
Have a great day.:-)
 
Ranch Hand
Posts: 514
1
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello!

This code you posted is absolutely correct and will never throw exception you can traverse Map in this loop and add elements to it !

Other people simply mix for loop with for-each loop!

HashMap cannot be traversed in foreach. HashMap does not return any view that allows to add new elements to HashMap.
All views returned by HashMap simply delegate to methods of HashMap therefore they are always consistent with current state of backing array.
HashMap does not support Iterator but views support.
If you obtained new instance of view's iterator you must not modify HashMap because subsequent call to iterator.next() or iterator.remove()
throws ConcurrentModificationException
Actually all these things and more read in my tutorial Internal life of HashMap. And read other tutorials they will help you very well to understand main collections and thus pass interview for Junior Java Developer.
 
Chan Ag
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

How about initializing in the Static block.



You're ( almost ) there, IMO. I think you're doing great.

Not sure if your current issue is resolved completely, cause we never got to hear your complete requirement in the first place. But looks like you just needed to have the initialization done only once.
Yeah?

Chan





 
What's a year in metric? Do you know this metric stuff tiny ad?
Building a Better World in your Backyard by Paul Wheaton and Shawn Klassen-Koop
https://coderanch.com/wiki/718759/books/Building-World-Backyard-Paul-Wheaton
    Bookmark Topic Watch Topic
  • New Topic