Meaningless Drivel is fun!*
The moose likes Threads and Synchronization and the fly likes Multi-threads access singleton Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Multi-threads access singleton" Watch "Multi-threads access singleton" New topic
Author

Multi-threads access singleton

ricky wong
Greenhorn

Joined: Jan 27, 2003
Posts: 22
Dear all,

I have a problem. If a singleton contains a Hashmap variable and it is accessed by different threads. Different threads put or get value to/from the Hashmap through the singleton reference. At some time, a thread cannot get a value from the Hashmap although this value is stored to Hashmap with the key before. Below are the sources :

public class DataMap
{
private static DataMap uniqueInstance = new DataMap ();
private HashMap htCache = null

private DataMap() {
htCache = new HashMap();
}

public static Singleton getInstance() {
return uniqueInstance;
}

public Object get(Object key) {
return htCache.get(key);
}

public void put(Object key, Object value) {
return htCache.put(key, value);
}
}

public class TestThread extends Thread {

public void run() {
....
if (true)
DataMap.getInstance().put(key, value);
else
Object obj = DataMap.getInstance().get(key);
....
}
}

A thread T1 will put a value with a key to HashMap in the Singleton DataMap and then another thread (or the same thread) T2 will get the value by using the key after several minutes. T2 may not get a value from HashMap. T1 and T2 threads are not in the same ThreadGroup. So should I add an object lock to synchronize the method "get" and
"put"? Anyone know why and please kindly help.

Thanks.
Ken Blair
Ranch Hand

Joined: Jul 15, 2003
Posts: 1078
Your question is very confusing. What are you trying to do?


A thread T1 will put a value with a key to HashMap in the Singleton DataMap and then another thread (or the same thread) T2 will get the value by using the key after several minutes. T2 may not get a value from HashMap.


What does that mean? If it's the same thread it's going to get a value. If it's a different thread and executes after the thread that put the value then it will get a value. If it's a different thread and executes while the other thread is putting the value then you're going to get undetermined behavior.


T1 and T2 threads are not in the same ThreadGroup.


The ThreadGroup has nothing to do with whether or not they can access the DataMap.


So should I add an object lock to synchronize the method "get" and "put"?


If you don't want DataMap to be accessed concurrently then I would mark both the put and get methods as synchronized or synchronize internally. Which you choose depends on the use and whether or not you need to be able to externally synchronize a series of invocations.
ricky wong
Greenhorn

Joined: Jan 27, 2003
Posts: 22
The running order to access the Singleton DataMap by different threads in the program within a short time is :

T1 puts value V1 with key K1 to DataMap.
T2 puts value V2 with key K2 to DataMap.
T3 puts value V3 with key K3 to DataMap.
T4 puts value V4 with key K4 to DataMap.
:
:
Ta gets value from DataMap with Key K1.
Tb gets value from DataMap with Key K2.
Tc gets value from DataMap with Key K3.
Td gets value from DataMap with Key K4.
:
:

I found that Ta could not get value from DataMap with Key 1 although T1 has been run and attempted to put value V1 with Key K1 to DataMap (according to my program log).

I guess the cause may be due to T1 have not put the value to DataMap successfully and Ta attempts to get value from DataMap. Do anyone know how to control the order? Use a queue??

Thanks.
Jon Egan
Ranch Hand

Joined: Mar 24, 2004
Posts: 83
Ricky,

As Ken mentioned, to be sure that T1 is not in the middle of the put when Ta tried the get with the same key, you would need to synchronize the get() and put() methods, like this:




It sounds like, though, from your last post, you are actually asking about how to be sure the put happens before the get (instead of in the reverse order). The synchronized methods will ensure that whichever method call is started first will finish before the other starts, but won't guarantee anything about the order of the two.

If you're interested in having one thread wait to do its task until it has been notify-ed that another thread has finished its task, look at Object.wait() and Object.notify().

Each "writer" thread would do its "put()", then call someObject.notify(). Each "reader" thread would call someObject.wait(), which would block until the notify() was called by the other thread.

It's been a while since I've had to mess around with wait() and notify(), but I think I remember there's a "gotcha" here, in that you have to be sure (somehow) that the "writer" thread doesn't start and finish (and call notify()) before the "reader" thread can call wait()... or else, it'll be waiting for a notify() that will never come, and hang forever.

Can someone who is more current on this confirm or deny that, and recommend a solution? Seems like catch-22 to me, at the moment: how do you guarantee the order of operations (waits and notifies) between threads, so that you know the mechanism for guaranteeing the order of operations (writes and reads) will work?

Anyway: once that's answered, the Object in question, in your case, might be the hash Key objects? But this depends on the two threads actually using the same instance of the Key object, not just two separate instances which are equivalent under the "equals()" method.... which is more strict than is usually required by HashMap. (Maybe in your app, there is some better candidate for the object to use for the wait() and notify() - in the snippet you gave the keys were the only obvious choice.)


And here are a couple of smart-aleck answers, in case you don't care for the one above:

  • your "put()" method is declared void, but returning Object
  • your "getInstance()" method is declared to return Singleton, but is returning a DataMap, which is not declared to implement or extend Singleton.

  • Neither of those are going to help get the desired results


    Hope some (any) of this has helped....

    -- Jon
    Ilja Preuss
    author
    Sheriff

    Joined: Jul 11, 2001
    Posts: 14112
    If just synchronizing put and get doesn't solve your problem, you should google for the "Producer Consumer" pattern.


    The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
    Ken Blair
    Ranch Hand

    Joined: Jul 15, 2003
    Posts: 1078
    Originally posted by Ilja Preuss:
    If just synchronizing put and get doesn't solve your problem, you should google for the "Producer Consumer" pattern.


    Aye, I was just wondering if this is what they're trying to accomplish or not. Looks more like an attempt to create a thread-safe HashMap more than anything else.
    Ken Blair
    Ranch Hand

    Joined: Jul 15, 2003
    Posts: 1078
    Originally posted by Jon Egan:
    Can someone who is more current on this confirm or deny that, and recommend a solution? Seems like catch-22 to me, at the moment: how do you guarantee the order of operations (waits and notifies) between threads, so that you know the mechanism for guaranteeing the order of operations (writes and reads) will work?


    Since it sounds like you're talking about the Producer/Consumer pattern then AFAIK as long as the consumer checks for availability before waiting it should be fine.
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: Multi-threads access singleton