Java concurrency Programming (iv) Synchronizing container classes

Source: Internet
Author: User
Tags concurrentmodificationexception

Synchronizing Container classes

The synchronization container classes in Java include vectors and Hashtable, which are part of the early-riser JDK, and also include some of the functionally similar classes added in JDK1.2, which are packaged classes of collections.synchronizedxxx, such as factory methods Created by the. These classes implement thread-safe methods all the same: encapsulate them and synchronize each public method so that only one thread can access the state of the container at a time.


problems with synchronizing container classes

The synchronization container classes are thread-safe, but in some cases, additional client locks are required to protect the composite operation.

1, iterative operation. Repeatedly accesses the element until it has traversed all the elements in the container.

2, jump operation. Finds the next element of the current element, based on the specified order.

3, the condition operation. For example, the "add if not" operation.

For example, for container traversal operations. These compliance operations are thread-safe without a client-side lock-up, but they may behave unexpectedly when other threads modify the container concurrently. such as throwing arrayindexoutofboundsexception.

Because the synchronization container class adheres to the synchronization policy, which is to support client-side locking, it is possible to create new operations that, as long as we know which locks should be used, are atomic, as do the other operations of the container. The synchronization container class protects each of its methods according to its own lock.

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

This iterative operation has a race condition, that is, its correctness depends on the order in which multiple threads are executed. If there is another thread between size and get that modifies the Vector, it can cause an error. If another thread deletes an element while iterating over the Vector, and the two operations are executed alternately, the iterative method throws a ArrayIndexOutOfBoundsException exception.

Although this iterative operation may throw an exception, it does not mean that the Vector is not thread-safe. The state of the Vector is still valid , and the thrown exception is consistent with its specification. Then, it is obviously not desirable to throw an exception in a simple operation such as reading the last element or iteration.

We can solve the problem of unreliable iterations by locking the client, but sacrificing some of the scalability. By holding a vector lock during the iteration, it is possible to prevent other threads from modifying the vector in an iterative device, as shown in the following program, which causes other threads to be inaccessible to him during the iteration, thereby reducing concurrency.

Synchronized (vector) {for (int i = 0; i < vector.size (); i++) {dosomething (Vector.get (i));}}



iterators and Concurrentmodificationexception

The method used is Iterator whether the container is iterated directly or in the syntax of the For-each loop. However, if there are other threads that modify the container concurrently, even using an iterator will not prevent the container from being locked in the iteration. The iterator that designs the synchronization container class is, and does not take into account the problem of concurrent modifications, and the behavior they exhibit is " Timely failure " (fail-fast). This means that the concurrentmodificationexception exception is thrown when they find that the container has been modified during the iteration.

This "just-in-time failure" Iterator is not a complete processing mechanism, but only captures this error and alerts you. They do this by associating the counter changes with the container: If the iteration device counter is modified, then hasnext or next will throw concurrentmodificationexception.

Iterative device locking brings a number of problems

If the container is large, subsequent threads will wait for a longer period of time. Locks are held when dosomething is called, and may result in deadlocks. Locking a container for a long time can reduce the scalability of the program. The longer the lock is held, the more intense the competition may be, and if multiple threads are waiting, the throughput and CPU utilization will be greatly reduced.

If you do not want to lock, an alternative is to "clone" the container and iterate over the copy. Because the replica is enclosed within the thread, other threads do not operate on the iteration device, which avoids throwing concurrentmodificationexception. But the problem is that cloning has a significant performance overhead. The quality of this approach depends on a number of factors, including the size of the container, the work performed on each element, the frequency with which the iteration is invoked relative to the other operations of the container, and the demand for response time and throughput.


Hide Iterators

In some cases, the use of iterators is not so obvious. Look at the following example.

public class Iteratortest{private Final static set<integer> Set = new hashset<integer> ();p ublic static void PR Int () {System.out.print (set);} Public synchronized void Add (Integer i) {set.add (i);}}

The Print method may throw concurrentmodificationexception exceptions. This is because the compiler converts the connection operation of a string to call Stringbuilder.append (Object), which in turn invokes the ToString () method of the container, and the ToString method of the standard container iterates over the container and calls on each element ToString to generate a formatted representation of the contents of the container.

The real problem, of course, is that iteratortest is not thread-safe. Before you can use the set in println, you must first get the iteratortest lock, but this requirement is often overlooked in debug code and in log code .

Accordingly, the container's hashcode and equals methods also perform iterative operations indirectly, which occurs when the container is an element or a key value of 01 containers. Similarly, methods such asContainsall,removeall , and Retainall , as well as constructors that use containers as parameters, iterate over the container. All of these indirect iterators can throw concurrentmodificationexception.

Java concurrency Programming (iv) Synchronizing container classes

Related Article

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.