Java concurrent programming (4) Synchronous container class

Source: Internet
Author: User
Tags concurrentmodificationexception

Java concurrent programming (4) Synchronous container class
Synchronous container class

The synchronization container classes in Java include Vector and Hashtable, which are part of the early-rising JDK. In addition, they also include some similar functions added in JDK1.2. These synchronous encapsulation classes are collected by Collections. synchronizedXxx and other factory methods. These classes implement thread security methods in the same way: encapsulate them and synchronize each public method so that only one thread can access the container status at a time.


Problems with the synchronization container class

Synchronization containers are thread-safe, but in some cases, extra client locks are required to protect compound operations.

1. Iterative operation. Access elements repeatedly until all elements in the container are traversed.

2. Redirect operation. Find the next element of the current element in the specified order.

3. Conditional operation. For example, "add if no" operation is available.

For example, for a container traversal operation. These compliance operations are still thread-safe without locking the client. However, when other threads modify containers concurrently, they may behave unexpectedly. For example, ArrayIndexOutOfBoundsException is thrown.

Because the synchronization container class must comply with the synchronization policy, that is, the client can be locked, so we can create some new operations, as long as we know which lock should be used, these new operations are atomic operations like other operations in the container. The synchronization container class protects each of its methods based on its own locks.

For (int I = 0; I
 
  
This type of iteration operation has a race condition, that is, its correctness depends on the execution sequence of multiple threads. If another thread between size and get modifies the Vector, an error may occur. If the other thread deletes an element when performing an iteration on the Vector and the two operations are executed alternately, this iteration method throws an ArrayIndexOutOfBoundsException exception.

Although this iteration operation may throw an exception, it does not mean that the Vector is NOT thread-safe. The Vector status is still valid, and the thrown exception is also consistent with its specification. Then, throwing an exception in a simple operation like reading the last element or iteration is obviously not expected.

We can solve the problem of unreliable iteration by locking the client, but we need to sacrifice some scalability. By holding the Vector lock during iteration, other threads can prevent modifying the Vector in the iteration device, as shown in the following program. This will cause other threads to be unable to access the Vector during iteration, therefore, concurrency is reduced.

synchronized (vector) {for (int i = 0; i < vector.size(); i++) {doSomething(vector.get(i));}}



Iterator and ConcurrentModificationException

Whether it is a direct iteration or container iteration in the for-each loop syntax, the method used is Iterator. However, if other threads concurrently modify the container, even the iterator cannot avoid locking the container in the iterator. The design of the iterator for the synchronization container class is that the concurrent modification issue is not taken into account, and their behavior is "fail-fast. This means, but they will throw a ConcurrentModificationException when the container is modified during iteration.

This "timely failure" iterator is not a complete processing mechanism, but only captures such errors and sends an alert. Their implementation method is to associate the counter changes with the container: If the counter of the iterative device is modified, hasNext or next throws ConcurrentModificationException.

Iterative device locking will bring about a series of problems

If the container size is large, the subsequent threads will wait for a long time. A lock is held when doSomething is called, And a deadlock may occur. Locking the container for a long time will reduce the scalability of the program. If the lock is held for too long, the competition may become more intense. If multiple threads are waiting, the throughput and CPU utilization will be greatly reduced.

If you do not want to lock, an alternative method is to "clone" the container and iterate on the copy. Because copies are closed in the thread, other threads do not operate on them in the iterative device. This avoids throwing ConcurrentModificationException to hide it. However, the problem is that cloning has significant performance overhead. The quality of this method depends on multiple factors, including the container size, the work executed on each element, the call frequency of iterative operations relative to other operations in the container, and response time and throughput.


Hide iterator

In some cases, the use of the iterator is not so obvious. Let's look at the example below.

public class IteratorTest{private final static Set
   
     set = new HashSet
    
     ();public static void print() {System.out.print(set);}public synchronized void add(Integer i){set.add(i);}}
    
   

The print method may throw a ConcurrentModificationException exception. This is because the compiler converts the string connection operation to call StringBuilder. append (Object), and this method will call the toString () method of the container. The toString method of the standard container will iterate the container, toString is called on each element to generate a formatted representation of the container content.

Of course, the real problem is that IteratorTest is NOT thread-safe. Before using the set in println, you must first obtain the IteratorTest lock, but this requirement is often ignored in debugging code and Log Code.

Correspondingly, the hashCode and equals methods of the container will also perform iteration operations in a ground manner. This happens when the container acts as an element or key value of a zero container. Similarly, methods such as containsAll, removeAll, and retainAll, as well as constructors that use the container as parameters, will iterate over the container. All these indirect iterators may throw ConcurrentModificationException.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.