Thread safe container class

original
2013/05/02 21:10
Reading 522

Thread safety: When multiple threads access a class, no matter what scheduling method the runtime environment uses or how these threads execute alternately, and no additional synchronization or collaboration is required in the main calling code, this class can show correct behavior, so it is called thread safety.

Common container classes
Thread safe classes: Vector and Hashtable
Thread unsafe classes: ArrayList and HashMap

HashMap instance:

 public class MainClass { public static Map<String, String> hashMap = new HashMap<String, String>(); public static void main(String[] args) throws InterruptedException { // hashMap = Collections.synchronizedMap(hashMap); Thread t1 = new Thread() { public void run() { for (int i = 0;  i < 25; i++) { hashMap.put(String.valueOf(i), String.valueOf(i)); } } }; Thread t2 = new Thread() { public void run() { for (int j = 0;  j < 25; j++) { hashMap.put(String.valueOf(j), String.valueOf(j)); } } }; t1.start(); t2.start(); Thread.sleep(1000); for (int i = 0;  i < 25; i++) { System.err.println(i + ":" + hashMap.get(String.valueOf(i))); } } }
The printing result is unstable and often has wrong values
0:null
1:1
2:2
3:null
4:4
5:null


Cause analysis:

 public V put(K key, V value) { ... addEntry(hash, key, value, i); ... } void addEntry(int hash, K key, V value, int bucketIndex) { Entry<K,V> e = table[bucketIndex]; table[bucketIndex] = new Entry<K,V>(hash, key, value, e); if (size++ >= threshold) resize(2 * table.length); } void resize(int newCapacity) { Entry[] oldTable = table; int oldCapacity = oldTable.length; if (oldCapacity == MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return; } Entry[] newTable = new Entry[newCapacity]; transfer(newTable); table = newTable; threshold = (int)(newCapacity * loadFactor); }

From the code, we can see that if the size of the hash table is found to exceed the threshold threshold, the resize method will be called to expand the capacity twice as much as the original, and the method of expanding the capacity is to create a new Entry [].  
If, by default, a HashMap has a capacity of 16 and a load factor of 0.75, the threshold value is 12, so when the put value in the HashMap reaches 12, it will automatically expand twice. If two threads simultaneously encounter a HashMap that is a multiple of 12, they may encounter problems in the process of transferring oldTable to newTable, This results in the value storage exception of the final HashMap.

JDK1.0 introduces the first associated collection class HashTable, It is thread safe. All HashTable methods are synchronized.
JDK2.0 introduces HashMap, which provides an asynchronous base class and a synchronized wrapper synchronized Map. SynchronizedMap is called a conditional thread safe class.
The JDK5.0util.concurrent package introduces ConcurrentHashMap, a thread safe implementation of Map, which provides more flexibility than synchronized Map. Simultaneous read and write operations can be executed concurrently.

ArrayList instance:

 public static List<String> list = new ArrayList<String>(); public static void main(String[] args) throws InterruptedException { //		list = Collections.synchronizedList(list); Thread t1 = new Thread() { public void run() { for (int i = 0;  i < 25; i++) { list.add(String.valueOf(i)); } } }; Thread t2 = new Thread() { public void run() { for (int j = 25;  j < 50; j++) { list.add(String.valueOf(j)); } } }; t1.start(); t2.start(); Thread.sleep(1000); for (int i = 0;  i < 50; i++) { System.err.println(i + ":" + list.get(i)); } }
The result is abnormal:
44:48
45:49
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 46, Size: 46
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.get(ArrayList.java:322)

at map.Test.main(Test.java:37)

Cause analysis:

 public boolean add(E e) { ensureCapacity(size + 1);  //  Increments modCount!! elementData[size++] = e; return true; }

The multi-threaded operation led to the inconsistency of the expansion and assignment operations, which led to errors.
The util. concurrent package also provides a thread safe alternative to ArrayList, CopyOnWriteArrayList.

Vector and Hashtable add the synchronized keyword to their respective methods to maintain synchronization.
We often understand the concept of synchronization as a mutually exclusive way. In fact, synchronization can not only prevent a thread from seeing the object in an inconsistent state, but also ensure that every thread entering the synchronization method or synchronized code block can see all previous modification effects protected by the same lock.

Expand to read the full text
Loading
Click to join the discussion 🔥 (1) Post and join the discussion 🔥
Reward
one comment
one Collection
zero fabulous
 Back to top
Top