2

I have a instance of a object which performs very complex operation.

So in the first case I create an instance and save it it my own custom cache.

From next times whatever thread comes if he finds that a ready made object is already present in the cache they take it from the cache so as to be good in performance wise.

I was worried about what if two threads have the same instance. IS there a chance that the two threads can corrupt each other.

 Map<String, SoftReference<CacheEntry<ClassA>>> AInstances= Collections.synchronizedMap(new HashMap<String, SoftReference<CacheEntry<ClassA>>>());
user882196
  • 1,691
  • 9
  • 24
  • 39

4 Answers4

2

There are many possible solutions:

  • Use an existing caching solution like EHcache
  • Use the Spring framework which got an easy way to cache results of a method with a simple @Cacheable annotation
  • Use one of the synchronized maps like ConcurrentHashMap
  • If you know all keys in advance, you can use a lazy init code. Note that everything in this code is there for a reason; change anything in get() and it will break eventually (eventually == "your unit tests will work and it will break after running one year in production without any problem whatsoever").

ConcurrentHashMap is most simple to set up but it has simple way to say "initialize the value of a key once".

Don't try to implement the caching by yourself; multithreading in Java has become a very complex area with Java 5 and the advent of multi-core CPUs and memory barriers.

[EDIT] yes, this might happen even though the map is synchronized. Example:

SoftReference<...> value = cache.get( key );
if( value == null ) {
    value = computeNewValue( key );
    cache.put( key, value );
}

If two threads run this code at the same time, computeNewValue() will be called twice. The method calls get() and put() are safe - several threads can try to put at the same time and nothing bad will happen, but that doesn't protect you from problems which arise when you call several methods in succession and the state of the map must not change between them.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
0

Assuming you are talking about singletons, simply use the "demand on initialization holder idiom" to make sure your "check" works across all JVM's. This will also make sure all threads which are requesting the same object concurrently wait till the initialization is over and be given back only valid object instance.

Here I'm assuming you want a single instance of the object. If not, you might want to post some more code.

Sanjay T. Sharma
  • 22,857
  • 4
  • 59
  • 71
0

Ok If I understand your problem correctly, you are worried that 2 objects changing the state of the shared object will corrupt each other.

The short answer is yes they will.

If the object is expensive in creation but is needed in a read only manner. I suggest you make it immutable, this way you get the benefit of it being fast in access and at the same time thread safe.

If the state should be writable but you don't actually need threads to see each others updates. You can simply load the object once in an immutable cache and just return copies to anyone who asks for the object.

Finally if your object needs to be writable and shared (for other reasons than it just being expensive to create). Then my friend you need to handle thread safety, I don't know your case but you should take a look at the synchronized keyword, Locks and java 5 concurrency features, Atomic types. I am sure one of them will satisfy your need and I sincerely wish that your case is one of the first 2 :)

MahdeTo
  • 11,034
  • 2
  • 27
  • 28
0

If you only have a single instance of the Object, have a quick look at:

Thread-safe cache of one object in java

Other wise I can't recommend the google guava library enough, in particular look at the MapMaker class.

Community
  • 1
  • 1
Gareth Davis
  • 27,701
  • 12
  • 73
  • 106