Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hashtable: why is get method synchronized?

I known a Hashtable is synchronized, but why its get() method is synchronized?

Is it only a read method?

like image 789
user1626860 Avatar asked Jan 14 '13 01:01

user1626860


2 Answers

If the read was not synchronized, then the Hashtable could be modified during the execution of read. New elements could be added, the underlying array could become too small and could be replaced by a bigger one, etc. Without sequential execution, it is difficult to deal with these situations.

However, even if get would not crash when the Hashtable is modified by another thread, there is another important aspect of the synchronized keyword, namely cache synchronization. Let's use a simplified example:

class Flag {
  bool value;

  bool get() { return value; } // WARNING: not synchronized
  synchronized void set(bool value) { this->value = value; }
}

set is synchronized, but get isn't. What happens if two threads A and B simultaneously read and write to this class?

1. A calls read
2.                 B calls set
3. A calls read

Is it guaranteed at step 3 that A sees the modification of thread B?

No, it isn't, as A could be running on a different core, which uses a separate cache where the old value is still present. Thus, we have to force B to communicate the memory to other core, and force A to fetch the new data.

How can we enforce it? Everytime, a thread enters and leaves a synchronized block, an implicit memory barrier is executed. A memory barrier forces the cache to be updated. However, it is required that both the writer and the reader have to execute the memory barrier. Otherwise, the information is not properly communicated.

In our example, thread B already uses the synchronized method set, so its data modification is communicated at the end of the method. However, A does not see the modified data. The solution is to make get synchronized, so it is forced to get the updated data.

like image 56
Philipp Claßen Avatar answered Oct 11 '22 13:10

Philipp Claßen


Have a look in Hashtable source code and you can think of lots of race conditions that can cause problem in a unsynchronized get() .

(I am reading JDK6 source code)

For example, a rehash() will create a empty array, and assign it to the instance var table, and put the entries from old table to the new one. Therefore if your get occurs after the empty array assignment, but before actually putting entries in it, you cannot find your key even it is in the table.

Another example is, there is a loop iterate thru the linked list at the table index, if in middle in your iteration, rehash happens. You may also failed to find the entry even it exists in the hashtable.

like image 44
Adrian Shum Avatar answered Oct 11 '22 12:10

Adrian Shum