0
public class PlanetInfo {
    String planetName="";
    int a;
    int b;
    int c;

    PlanetInfo(planetname){
        planetName = planetname;
        if(planetName.equals("earth")){
            a=1;
            //....
        }
        else if(planetName.equals("mars")){
            a=2;
            //....
        }
    }       
}

public final class Infos {
    static final LinkedList<PlanetInfo> planets = new LinkedList<PlanetInfo>();

    private static synchronized PlanetInfo internal_getPlanetInfo(String planetName){
        for(int i=0;i<planets.size();i++){
            if(planets.get(i).planetName.equals(planetName)){
                //return existing PlanetInfo:
                return planets.get(i);
            }
        }

        //if not found then create and return a new one:
        return new PlanetInfo(planetName);

    }

    public static PlanetInfo getPlanetInfo(String planetName){
        return internal_getPlanetInfo(planetName);
    }
}


public class Foo {    
    PlanetInfo planetinfo = null;
    public Foo(aplanet){
        planetInfo = Infos.getPlanetInfo(aplanet);
    }

    public void dosomthing(){
        if(planetInfo.a==1){//please, do not wonder about thread-safe here, it's just a simplification...
            // etc....
        }
    }


}

it is vary rare that a new PlanetInfo need to be created, but it happens. once a PlanetInfo created and added to Infos.planets, IT WILL NEVER BE REMOVED. most of the time, Infos.planets is practically read-only.

there are many many threads that have instance of Foo, they all need a pointer to a PlanetInfo object. as you can see, internal_getPlanetInfo is synchronized.

i wonder if i can change the code, so it may do 2 attempts to find the desired PlanetInfo. the first attempt would be Asynchronously, and (if not found then do) the second synchronously. so... the mothod getPlanetInfo will do the vary same for-loop as method internal_getPlanetInfo. thus, most of the time threads will not lock each other.

the thing i have in mind is that a thread may have a "stale"-copy of Infos.planets, but! the only potential problem with this "stale"-copy is that it misses an item that was added some time later. so if the desired item not found then we look for it using the "master"-copy.

public static PlanetInfo getPlanetInfo(String planetName){
    //try to find it Asynchronously:
    for(int i=0;i<planets.size();i++){
        if(planets.get(i).planetName.equals(planetName)){
            return planets.get(i);
        }
    }
    //if not found then do it synchronously:
    return internal_getPlanetInfo(planetName);
}

any comments would be appreciated!

ido.

1 Answers1

0

What you are describing is actually an excellent idea especially in the context of a high level of concurrency. The below pattern will ensures that "value" gets computed only once and that the critical section gets executed a minimum number of times. In a language-neutral pseudo code the pattern is as follows:

if value is-not-available then
    // Entering critical section
    if value is-not-available then
        value = comupte-the-value
    // Exit critical section.
}
return value;

I would suggest, if its not already the case, that PlanetInfo objects be immutable and that when their information does change then you need only create a new object with the changed values. Read-only objects avoid lots of concurrency issues.

The staleness issue can be easily be solved with an additional level of indirection. Instead Foo holding on to a PlanetInfo reference they should keep a planetInfoIndex (into Info.planets). When new information is known about the planet then the reference at that index is replaced with a new immutable object. The next time any Foo objects accesses the info the new object will be returned.

aLevelOfIndirection
  • 3,522
  • 14
  • 18