This discussion is archived
11 Replies Latest reply: Dec 13, 2012 12:32 PM by Manjit RSS

One thread adding/updating value  and other thread getting values....issue

Manjit Newbie
Currently Being Moderated
am using a spring bean (singleton) and this is how it looks like

public class MySingletonService {

private Map<String, List<TaskVO>> alerts = new HashMap<String, List<TaskVO>>();



//spring will call this method every 15 minutes
public void pollDatabase() {


//initialize the alerts instance variable and create/fill the alerts instance variable with new alerts for the employee(from database) .The key for the hashmap is the employee id
}




//some client code (e.g. GUI) will call this method to get the alert for the operator id.This can be called anytime to get the latest info from the alert Map
public List<TaskAlertVO> getOutstandingAlerts(String operatorId) {
return alerts.get(operatorId);
}
}

The issue here is that when getOutstandingAlerts is invoked by a thread,some other thread(Spring) calling the pollDatabase method might be updating the value.Please give me some idea and solution to get around this issue.
I was thinking of creating a copy of alerts instance variable in the getOutstandingAlerts method and then use the copy to find the key and return the alert for that operator id.This way we dont have to worry about data conflict.

Please advice
  • 1. Re: One thread adding/updating value  and other thread getting values....issue
    DrClap Expert
    Currently Being Moderated
    Why not just use a ConcurrentHashMap?
  • 2. Re: One thread adding/updating value  and other thread getting values....issue
    TPD-Opitz-Consulting-com Expert
    Currently Being Moderated
    why didn' you learn the
    -tag trick yet?
    
    bye
    TPD                                                                                                                                                                                                        
  • 3. Re: One thread adding/updating value  and other thread getting values....issue
    jtahlborn Expert
    Currently Being Moderated
    if the pollDatabase() method is getting a complete new copy of the alerts every time, and the alerts map isn't being modified at all after load, then you can just:

    - make the alerts member variable volatible
    - create a new HashMap each time pollDatabase() is called, fill it in, and then assign it to the alerts member variable.
  • 4. Re: One thread adding/updating value  and other thread getting values....issue
    Manjit Newbie
    Currently Being Moderated
    Clap,initially I did make it ConcurrentHashmap ,but I believe concurrent hashmap doesnt lock the collection during a get.This means when one thread is updating the map ,the second thread can get values from the map.The get operation of the map doesnt lock the map.

    Thanks
    M
  • 5. Re: One thread adding/updating value  and other thread getting values....issue
    Manjit Newbie
    Currently Being Moderated
    jtahlborn ,you are right that pollDatabase operation creates a brand new copy of alerts ,but getOutstandingAlerts might try to retrieve a value when the pollDatabase operation is updating value.Making the instance variable volatile will not help here.


    I was thinking that getOutstandingAlerts method should create an exact copy of alert and retrieve the value from the copy ,rather than the original alert.This way the client code dont have to worry about what the pollDatabase does to the original alert instance variable.Is my strategy good.
  • 6. Re: One thread adding/updating value  and other thread getting values....issue
    jtahlborn Expert
    Currently Being Moderated
    Manjit wrote:
    jtahlborn ,you are right that pollDatabase operation creates a brand new copy of alerts ,but getOutstandingAlerts might try to retrieve a value when the pollDatabase operation is updating value.Making the instance variable volatile will not help here.
    which one is it? if pollDatabase is creating a new map, then nothing it is doing will affect getOutstandingAlerts.
    I was thinking that getOutstandingAlerts method should create an exact copy of alert and retrieve the value from the copy ,rather than the original alert.This way the client code dont have to worry about what the pollDatabase does to the original alert instance variable.Is my strategy good.
    maybe there is more code that you aren't showing here? you are essentially describing a copy-on-read solution, which is very inefficient if reads outnumber writes. my proposed solution is sort of like copy-on-write. if all the getOutstandingAlerts method is doing is calling get() on the map, my proposed solution will work just fine.
  • 7. Re: One thread adding/updating value  and other thread getting values....issue
    Manjit Newbie
    Currently Being Moderated
    jtalborn ,I did put in my entire code.Your understanding about my code is also correct.

    The pollDatabase create a breand new copy and initializes the instance variable.The getOutstandingAlert simply gets latest value from the instance map variable.


    So imagine the poll database (it polls the database every 15 minutest) puts "new AlertVO(1,2,3),new AlertVO(4,5,6),new AlertVO(7,8,9)) the map for employee id (key of the hasmap) "Supervisor".

    The getOutstandingAlerts will get the three AlertVO object for "Supervisor".When the client is still looking at new AlertVO(1,2,3),the pollDatabase operation might initialize the map to some other values for "Supervisor" say "new AlertVO(11,12,13),new AlertVO(14,15,16),new AlertVO(17,18,19)).Isnt this corrupted data that the client (say UI code)will be lookint at ?

    Am I missing something here.What I said above is what concerns me.

    I talked about creatng a new copy in get operation is simply because the client code will not be affected even if the pollDatabase operation changes the value (voloatile will create this problem)
  • 8. Re: One thread adding/updating value  and other thread getting values....issue
    Manjit Newbie
    Currently Being Moderated
    if the pollDatabase() method is getting a complete new copy of the alerts every time, and the alerts map isn't being modified at all after load, then you can just:

    - make the alerts member variable volatible
    - create a new HashMap each time pollDatabase() is called, fill it in, and then assign it to the alerts member variable.



    Jtalhorn,I think I got your point.Basically you are suggesting that by creating a brand new map in each pollDatabase operation, then I dont have to worry about get operation ,simply because the client code is still looking at old memory location(old copy) and hence should not worry about values getting changes by pollDatabase method.

    I got it.

    But the small doubt is that why even I should bother about making the instance variable volatile ? Your suggestion should work without making it volatile
  • 9. Re: One thread adding/updating value  and other thread getting values....issue
    DrClap Expert
    Currently Being Moderated
    Manjit wrote:
    Clap,initially I did make it ConcurrentHashmap ,but I believe concurrent hashmap doesnt lock the collection during a get.This means when one thread is updating the map ,the second thread can get values from the map.The get operation of the map doesnt lock the map.
    Yes, that's the whole point of ConcurrentHashMap. I don't see why it's a problem for your design -- not that I could tell much about your design from what you posted, but it sure looked like one thread was doing a "put" and the other thread was doing a "get". If that's all it is then ConcurrentHashMap should be fine.

    Unless you found some actual problems and not just some potential problems which you thought up.
  • 10. Re: One thread adding/updating value  and other thread getting values....issue
    jtahlborn Expert
    Currently Being Moderated
    Manjit wrote:
    jtahlborn wrote:
    if the pollDatabase() method is getting a complete new copy of the alerts every time, and the alerts map isn't being modified at all after load, then you can just:

    - make the alerts member variable volatible
    - create a new HashMap each time pollDatabase() is called, fill it in, and then assign it to the alerts member variable.
    Jtalhorn,I think I got your point.Basically you are suggesting that by creating a brand new map in each pollDatabase operation, then I dont have to worry about get operation ,simply because the client code is still looking at old memory location(old copy) and hence should not worry about values getting changes by pollDatabase method.

    I got it.

    But the small doubt is that why even I should bother about making the instance variable volatile ? Your suggestion should work without making it volatile
    because volatile ensures correct memory visibility between threads. if you didn't use volatile, then a caller to getOutstandingAlerts() could see some partially initialized/corrupt version of the map.
  • 11. Re: One thread adding/updating value  and other thread getting values....issue
    Manjit Newbie
    Currently Being Moderated
    Thank Clap and thank you jtalhorn . I got my answer from your response.

    Thanks again guys

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points