• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Static variable is thread safe?

 
Gireesh Giri
Greenhorn
Posts: 23
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi All,
I am using a static HashTable for multi thread model in java class, all the threads has to access the HashTable, is it will work fine?
Thanks in advance.
 
Mohamed Sanaulla
Saloon Keeper
Posts: 3159
33
Google App Engine Java Ruby
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You would have to synchronize its access. As it is not thread safe .
 
Nuwan Arambage
Ranch Hand
Posts: 76
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
yes definitely static variables are not thread safe.. you have to synchronize the block.... still totally correct.But my point of view , why static variable are not thread safe is the smart question.

Static variables are resides inside the method area.Method area is shared among all the threads in the particular JVM because of that you have to synchronize the code block to coordinate threads.

 
Aditya Jha
Ranch Hand
Posts: 227
Eclipse IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Nuwan I'm not sure what exactly you meant here. Static variables are loaded along with loading of the class itself, without needing to create any 'Method' area.

As for the original question - Hashtable by itself is synchronized. So, if you are declaring a static final Hashtable and also intializing it at the time of declaration itself, all operations will be thread-safe on this Hashtable instance without you having to write any code for synchronization. If you're instantiating the Hashtable at a later point in time (and not with declaration), then there is a possibility that you need some amount of synchronization.

Also, consider using ConcurrentHashMap instead of Hashtable if you're using JDK 5 or above.
 
giridharan radhakrishnan
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


If multiple threads access the same hashmap you may result in concurrency exception and if you use hashtable we cannot say that multiple threads can access the same hashtable as it is synchronized. Try creating a static hashtable and create multiple threads to access the same hashtable it might throw exception but point at which it throws exception might vary each time when you run.
Try using ConcurrentHashMap<K,V> which is provided as part of JDK5 /6
 
Aditya Jha
Ranch Hand
Posts: 227
Eclipse IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Try creating a static hashtable and create multiple threads to access the same hashtable it might throw exception but point at which it throws exception might vary each time when you run.


Nothing of this sort is gonna' happen. No exceptions will be raised. Hashtable is capable of handling simultaneous operations in different threads (which won't happen, technically, as it is synchronized).

I suggested ConcurrentHashMap for the simple reason of enhancing performance. The question of why the performance is better with ConcurrentHashMap as opposed to a Hashtable is beyond the scope of this question. for starters, I would recommend reading the JavaDoc for both classes.
 
Steve Luke
Bartender
Posts: 4181
21
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There is a bit more to consider for Hashtable synchronization as well. Single method calls on a Hashtable are synchronized, but that does not guarantee sequential consistency. So if you need successive operations to be performed in a safe manner you would need additional synchronization. One example of this would be iterating over the contents of the Hashtable (or even worse Enumerating over them). If one thread is iterating and another is modifying the Hashtable then the iteration can fail. If you are using enumerators you could be left with a mess.

Declaring the Hashtable as final doesn't solve this because it just prevents the reference variable from changing. It does not prevent the Hashtable being referenced from being modified. So with Hashtables, any multiple-access operations that require consistency between steps need to be synchronized.

An example that is often forgotten is the 'test - then add' paradigm. You test if a key or value is in the table, if it is there you modify the table and if it is not you add it with some default value. For example, you have code like this:

That wouldn't be thread safe, because the 'word' could be added to or removed from the list after the 'table.contains(word)' line is called, and before the conditional block is executed. Also, the value stored in the table for the word could change between the get and the put making the value you put into the table not correct.

Using ConcurrentHashMap fixes the problems with Iterators and Enumerators. It also fixes the first problem with the code above. It does not fix either of the problems with the above mentioned code, though.
 
Aditya Jha
Ranch Hand
Posts: 227
Eclipse IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Steve You raised a valid point. However, as you clearly mentioned, the problem you described can happen with ConcurrentHashMap too. In fact, it is much easier to resolve with Hashtable (a down point of ConcurrentHashMap, you could say).



The above code resolves the problem with Hashtable. However, if we need to do the same with a ConcurrentHashMap, things will be a little tricky. We'll have to use a 'Lock' instance, and share it across all classes which make use of the ConcurrentHashMap. Every single operation on this ConcurrentHashMap will have to be under that lock, in order to make the above operation atomic.

Gurus, please correct me if I'm wrong.
 
Steve Luke
Bartender
Posts: 4181
21
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You might want to try some more 'optimistic.' For example, you would use the putIfAbsent() method to add a value only if it didn't yet exist, and the replace(key, oldValue, newValue) to ensure you put the value back in only if it hasn't changed.



The optimistic approach doesn't always work (especially if there is a lot of modification to the list which would make the do{}while() loop have to repeat a lot). So be careful where you use it.

As for needing to pass the Lock around I have a couple of points:
1) I don't think you need to use a Lock, you could use normal synchronization just as you described above to handle it. You would need to synchronize all the modifications and methods that require sequential consistency that way - but simple single-step reads would still not need to be synchronized.
2) To prevent the need to pass a lock around you could force the centralization of modification of the Map, and any tasks which require sequential consistency. For example:

Here the Map is hidden inside the WordCounter class, private and hidden from being accessed from outside code. The methods can be called from lots of different threads. If you needed something to externally synchronize on you would roll that into your class and keep the content of the Map safe. You would publish read-only views of the Map if someone needed it...
 
Aditya Jha
Ranch Hand
Posts: 227
Eclipse IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Fair enough! Thanks.

I wonder why the internal locking of ConcurrentHashMap is not exposed with some methods, so that one can actually do myMap.getReadLock().lock(), or similar. Would have been good, I guess.
 
Henry Wong
author
Marshal
Pie
Posts: 21022
78
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Aditya Jha wrote:
I wonder why the internal locking of ConcurrentHashMap is not exposed with some methods, so that one can actually do myMap.getReadLock().lock(), or similar. Would have been good, I guess.


The implementation is incredibly optimistic -- there isn't any lock that will lock the whole map. The reads are pretty much all in parallel. And as for the writes, they are segmented, locking only a small section that this needed.


And quite frankly, the Map interface doesn't require this. And the only reason, IMHO, that HashTable exposes the lock, is because the iterator may not work without it. This is not an issue with the ConcurrentHashMap -- iterators work and provide a view at the time of creation.

Henry
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic